填充对象的简便方法

时间:2015-03-24 21:30:27

标签: asp.net-mvc architecture entity-framework-6

我有以下课程:

    public class SectionViewModel
    {
        private static EFModels.VTSEntities _db = new EFModels.VTSEntities();
        public int ID { get; set; }
        public string SectionName { get; set; }
        public bool Active { get; set; }
        public string SiteName { get; set; }
   }

我想从_db.Sections中选择一个元素并填充此类的对象。我可以这样做:

    public SectionViewModel(int ID)
    {
        var s = (from i in _db.Sections
                 where i.ID == ID
                 select new SectionViewModel()
                 {
                     ID = i.ID,
                     SectionName = i.SectionName,
                     Active = i.Active,
                     SiteName = i.Site.SiteName
                 }).FirstOrDefault();
        ID = s.ID;
        SectionName = s.SectionName;
        Active = s.Active;
    }

它可以工作,但是当字段数是十,代码是巨大的。我想写类似的东西

    // IT DOES NOT WORK, ONLY EXAMPLE
    public SectionViewModel(int ID)
    {
        this = (from i in _db.Sections
                 where i.ID == ID
                 select new SectionViewModel()
                 {
                     ID = i.ID,
                     SectionName = i.SectionName,
                     Active = i.Active,
                     SiteName = i.Site.SiteName
                 }).FirstOrDefault();
    }

增加:

创建SectionViewModel对象(它是一个View模型类):

    public ActionResult SectionForm(int? id)
    {
        SectionViewModel model = new SectionViewModel(id);
        return View(model);
    }

但是,当然,这是不可能的,因为“this”仅适用于阅读。有办法吗?

1 个答案:

答案 0 :(得分:2)

修改

好的,您可以从SectionViewModel构建Section,而不是Section。这有所不同,但我的原始答案仍有许多评论适用。

更好的方法是

public ActionResult SectionForm(int id)
{
    Section section = this._context.Sections.Find(id);
    SectionViewModel model = .... // Mapping code
    return View(model);
}

此部分// Mapping code可以是将属性从section复制到model的任何内容。您可以使用AutoMapper。

不在SectionViewModel的构造函数中执行此操作的原因是,首先不应存在静态上下文。您可以创建和处理上下文。但谁说SectionViewModel总是单独构建?也许在另一种方法中,您将返回它们的列表。单独创建每个模型的效率非常低。 AutoMapper's Project().To方法适用于那里。


原始文字

在构造函数中构造一个对象(这是部件var s = (...).FirstOrDefault()发生的事情),然后将其属性复制到构造函数的所有者,这是相同的类型Section,这是荒谬的。在查询中你从一个部分构造一个Section更荒谬。所以在运行声明后......

Section model = new Section(id);

...你构建了三个相同的Section,其中最后一个最终被使用:

第1节:from i in _db.Sections where i.ID == ID select i
第2节:select new Section() {...}
第3节:Section(int ID)

EF甚至不允许像

那样的声明
from i in _db.Sections
select new Section() {...}

它会告诉您无法在LINQ-to-Entities查询中构造实体。

但删除此select new Section() {...}甚至不是声音重构的开始。整个构造是荒谬的。

另一个不好的做法是拥有静态上下文。上下文的设计寿命较短,因为它们会缓存从数据库中获取的每个实体。静态上下文是内存泄漏。

实现目标的方法就是......

public ActionResult SectionForm(int id)
{
    Section model = this._context.Sections.Find(id);
    return View(model);
}

...其中this._context是每个控制器实例创建的VTSEntities实例(或由Inversion of Control容器注入){。p>

您的编程风格隐约让人联想到Active Record,这种模式与EF的存储库/工作单元模式不完美混合(其中DbSet是回购,而DbContext是一个UoW)。它还打破了构建EF的 persistance ignorance 原则。它破坏了查询可组合性,并且很容易导致n + 1查询。