填充对象的简单方法 [英] Easy way to fill object
问题描述
我有以下课程:
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 中选择一个元素并填充该类的对象.我可以这样做:
I want to select one element from _db.Sections and fill object of this class. I can do it like it:
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 works, but when count of fields is tens, code is huge. I would like to write something similar
// 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 对象(它是一个视图模型类):
Create SectionViewModel object (it's a View model class):
public ActionResult SectionForm(int? id)
{
SectionViewModel model = new SectionViewModel(id);
return View(model);
}
但是,当然,这是不可能的,因为this"仅供阅读.有什么办法吗?
but, of course, it's impossible because "this" is available only for read. Any way to do it?
推荐答案
编辑
好的,所以你从 Section
构建了一个 SectionViewModel
,而不是一个 Section
.这会有所不同,但我的原始答案中的许多评论仍然适用.
OK, so you construct a SectionViewModel
, not a Section
, from a Section
. That makes some difference, but still many remarks from my original answer apply.
更好的方法是
public ActionResult SectionForm(int id)
{
Section section = this._context.Sections.Find(id);
SectionViewModel model = .... // Mapping code
return View(model);
}
这部分//映射代码
可以是任何将属性从section
复制到model
的东西.您可以使用 AutoMapper.
This part // Mapping code
can be anything that copies properties from section
to model
. You could use AutoMapper.
在 SectionViewModel
的构造函数中不这样做的原因是首先不应该有静态上下文.您可以改为创建和处理上下文.但是谁说 SectionViewModel
总是单独构造的?也许在另一种方法中,您将返回它们的列表.单独创建每个模型会非常低效.AutoMapper 的 Project().To
方法在那里很合适.
The reason not to do this in SectionViewModel
's constructor is that there shouldn't be a static context there in the first place. You could create and dispose a context in stead. But who says that SectionViewModel
s are always constructed individually? Maybe in another method you will return a list of them. Creating each model separately would be highly inefficient. AutoMapper's Project().To
approach would be appropriate there.
原文
在构造函数中构造一个对象(这就是 var s = (...).FirstOrDefault()
部分发生的事情)然后将其属性复制到该对象的所有者是荒谬的构造函数,同类型,Section
.更荒谬的是,在查询中您还从一个部分构造一个Section
.所以在运行语句之后...
It's absurd to construct an object in a constructor (which is what happens by the part var s = (...).FirstOrDefault()
) and then copy its properties to the owner of the constructor, which is the same type, Section
. It's even more absurd that in the query you also construct a Section
from a section. So after running the statement...
Section model = new Section(id);
...你已经构建了三个相同的Section
,最后一个使用了:
...you have constructed three identical Section
s of which the last one is finally used:
Section 1: from i in _db.Sections where i.ID == ID select i
.
第 2 节:select new Section() {...}
第 3 节:Section(int ID)
Section 1: from i in _db.Sections where i.ID == ID select i
.
Section 2: select new Section() {...}
Section 3: Section(int ID)
而且 EF 甚至不允许像
And EF doesn't even allow a statement like
from i in _db.Sections
select new Section() {...}
它会告诉您不能在 LINQ-to-Entities 查询中构造实体.
It will tell you that you can't construct an entity in an LINQ-to-Entities query.
但是删除这个 select new Section() {...}
甚至不是声音重构的开始.整个结构是荒谬的.
But removing this select new Section() {...}
is not even the beginning of a sound refactoring. The whole construct is absurd.
另一个不好的做法是使用静态上下文.上下文被设计为具有较短的生命周期,因为它们缓存从数据库中获取的每个实体.静态上下文是内存泄漏.
Another bad practice is to have a static context. Contexts are designed to have a short lifespan, because they cache each entity they fetch from the database. A static context is a memory leak.
实现你想要的方法很简单......
The way to achieve what you want is simply...
public ActionResult SectionForm(int id)
{
Section model = this._context.Sections.Find(id);
return View(model);
}
...其中 this._context
是您的 VTSEntities
实例,它是为每个控制器实例创建的(或通过控制反转容器注入其中).
...where this._context
is an instance of your VTSEntities
that is created per controller instance (or injected into it by an Inversion of Control container).
你的编程风格有点让人想起Active Record,与 EF 的存储库/工作单元模式(其中 DbSet
是一个存储库,而 DbContext
是一个 UoW)不能很好地混合的模式.它还打破了构建 EF 的persistence ignorance 原则.它破坏了查询的可组合性,很容易导致 n + 1
个查询.
Your programming style is faintly reminiscent of Active Record, a pattern that doesn't mix well with EF's repository/unit of work pattern (where DbSet
is a repo and a DbContext
is a UoW). It also breaks the persistance ignorance principle that EF is built on. It breaks query composability and it easily causes n + 1
queries.
这篇关于填充对象的简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!