【问题标题】:Easy way to fill object填充对象的简单方法
【发布时间】:2015-05-28 09:25:15
【问题描述】:

我有以下课程:

    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;
    }

它可以工作,但是当字段数为 10 时,代码量很大。我想写一些类似的东西

    // 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 对象(它是一个视图模型类):

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

但是,当然,这是不可能的,因为“this”只能用于读取。有什么办法吗?

【问题讨论】:

  • @Gert Arnold,我已添加
  • 如果我正确理解您的问题,这就是为什么存在像 Automapper 这样的产品的原因。
  • 我建议您阅读有关如何使用 MVC + EF 的信息。你的代码是错误模式的密集集合,显然是受到过去编程传统的微弱回响的启发。回到绘图板。
  • 我读过很多这样的文章。你能描述一下为什么我的方法是错误的吗?如果有必要,我只想在构造函数中填充我的 View 模型。哪种模式被打破了?

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


【解决方案1】:

编辑

好的,所以你从Section 构造一个SectionViewModel,而不是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 的构造函数中不这样做的原因是首先不应该有静态上下文。您可以改为创建和处置上下文。但是谁说SectionViewModels 总是单独构建的?也许在另一种方法中,您将返回它们的列表。单独创建每个模型效率非常低。 AutoMapper's Project().To 方法在那里是合适的。


原文

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

Section model = new Section(id);

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

第 1 部分:from i in _db.Sections where i.ID == ID select i.
第二部分:select new Section() {...}
第三节: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 的一个实例,它是按控制器实例创建的(或由控制反转容器注入其中)。

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

【讨论】:

  • 我的 Section 类是 View Model 类,而不是 EF 类!所以,你的例子不合适。为了更清楚,我将在我的问题中将 Section 类删除到 SectionViewModel!
  • 并且为 View 使用 EF 模型类是非常糟糕的方法(我可以在您的控制器方法中看到)。 EF模型就是EF模型,View模型就是View模型!
  • 请看修改后的答案。
  • 如果我想要 2 个或更多实体(即 SectionViewModel 由 Sections 填充,一个参数来自 Sites),您的方法不合适
  • 我只是指出一个情况,为什么你的方法不能很好。您建议获取模型类的对象,然后复制到视图模型类的对象。
猜你喜欢
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多