【问题标题】:How to set this from Entity Framework using Linq如何使用 Linq 从 Entity Framework 进行设置
【发布时间】:2012-01-11 00:11:57
【问题描述】:

不久前,当我第一次使用 MVC 时,我陷入了胖控制器的陷阱。我的第一个应用程序使用 EF4 来制作我需要的所有模型。我只是把我所有的逻辑放到我的控制器动作中。虽然它有效,但绝对不是最佳实践方式。为了以正确的方式做到这一点,我开始尝试基于我的 EF 对象构建我的模型,以努力遵循瘦控制器的概念。

我在尝试找到填充模型的最佳方法时遇到了障碍。有没有办法运行 LINQ 查询并让它填充您的模型,而无需遍历属性以设置为另一个类?

类似这样的:

// from EF model built from database
public class MyEFObject
{
    public int ID {get; set;}
    public string Name {get; set;}
    public string Title {get; set;}
}

public class MyObjectModel : MyEFObject
{
    private Entities _data = new Entities();
    public MyObjectModel(int? id)
    {
        if(id.HasValue) // get an existing record
        {
           this = _data.MyEFObjects.Where(m => m.ID.Equals(id)).Single();
           // or populate right out of the query
           _data.MyEFObjects.Where(m => m.ID.Equals(id))
                         .Select(o => new {
                            this.ID = o.ID,
                            this.Name = o.Name,
                            this.Title = o.Title
                          }); 
        }
        else
        {
           // set defaults for a new MyObjectModel
        }  
    }

    public void Save()
    {
        // takes the current object and saves changes
    }
}

我知道您可以向 EF 实体对象添加一个函数,但我喜欢在一次调用中将创建或更新选项全部绑定(保存方法)。如果我必须从本质上重新创建我已经从我的 EF 对象中拥有的东西,我看不出这点会弄乱模型。如果我只是在一个接受填充对象的类上有一个方法,那么我的视图的可用模型的概念就被否定了。

【问题讨论】:

    标签: c# asp.net-mvc linq entity-framework-4


    【解决方案1】:

    Slauma 是对的。 LINQ to Entities 不会接受它。我尝试了发布内容的几个版本,但我发现我自己一团糟。我做到了可以设置实例值的地步,但是到那时 EF 不会注册已进行的更改并破坏了整个目的。可能有一种方法可以做到这一点,但截至目前,使其工作的步骤似乎有点矫枉过正。

    我最终得到了这样的结果:

    public class MyObjectModel : MyEFObject
    {
        public void Save(int? id, MyObjectModel model)
        {
           var data = new Entities();
           MyEFObject foo;
           if(id.HasValue)
           {  
               foo = data.MyEFObjects.Where(e => e.ID.Equals(id.Value)).Single();
           }
           else
           {
               foo = new MyEFObject();
           }
           foo.Name = model.Name; 
           foo.Title = model.Title;
    
           if(!id.HasValue)
           {
              data.MyEFObjects.AddObject(foo);
           }
    
           data.SaveChanges();
        }
    }
    

    我不想使用我的模型的两个实例,但它可以工作,而且我有我的精益控制器操作。

    【讨论】:

    • 我的错误,我在我的解决方案中输错了一些东西。我已经更新了帖子并添加了评论。
    【解决方案2】:

    你可以做的是拥有一个域模型、ef 模型和适配器。我认为这可以保持代码非常干净,并且很好地分离了映射逻辑。

    //Domain model to decouple from EF
    public class MyObjectModel
    { 
        public int ID {get; set;} 
        public string Name {get; set;} 
        public string Title {get; set;} 
    } 
    
    //Auto generated Entity Framework class
    public class MyEFObject
    { 
        public int ID {get; set;} 
        public string Name {get; set;} 
        public string Title {get; set;} 
    } 
    
    //Adapter responsible for mapping your data to your domain model
    public class MyObjectModelAdapter : MyEFObject
    {
        public MyObjectModelAdapter(MyEFObject entity)
        {
            if(entity != null)
            {
                this.ID = entity.ID;
                this.Name = entity.Name;
                this.Title = entity.Title;
            }
            else 
            { 
               // set defaults for a new MyObjectModel 
            }  
        }
    }
    

    那么基本用法是:

    new Entities().MyEFObjects.ToList().Select(x => new MyObjectModelAdapter(x));
    

    new MyObjectModelAdapter(new Entities().MyEFObjects.FirstOrDefault(x => x.ID.Equals(objectId)));
    

    如果您特别需要 MyObjectModel 列表,则可以执行以下操作:

    new Entities().MyEFObjects.ToList().Select(x => new MyObjectModelAdapter(x) as MyObjectModel);
    

    new MyObjectModelAdapter(new Entities().MyEFObjects.FirstOrDefault(x => x.ID.Equals(objectId)) as MyObjectModel;
    

    当然你不想像那样将你的实体上下文链接在一起,这只是为了展示用法。

    【讨论】:

    • 它不适用于 EF,因为在 LINQ to Entities 中不支持投影到在其构造函数中带有参数的类型。
    • @Slauma 感谢您指出这一点,我的解决方案中有一个错误。 ToList 应事先调用,以便首先执行查询。我已经使用这种方法一段时间了,对我来说效果很好。
    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多