容易的方法来填充对象 [英] Easy way to fill object
问题描述
我有以下类:
public class SectionViewModel
{
private static EFModels.VTSEntities _db = new EFModels.VTSEntities();
public int ID {get;组; }
public string SectionName {get;组; }
public bool Active {get;组; }
public string SiteName {get;组;
}
我想从_db.Sections中选择一个元素,并填充此对象类。我可以这样做:
public SectionViewModel(int ID)
{
var s =从我在_db.Sections
其中i.ID == ID
选择新的SectionViewModel()
{
ID = i.ID,
SectionName = i.SectionName ,
Active = i.Active,
SiteName = i.Site.SiteName
})。FirstOrDefault();
ID = s.ID;
SectionName = s.SectionName;
Active = s.Active;
}
它可以工作,但是当字段数为十时,代码是巨大的。我想写一些类似的东西。
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
{
this =(从我在_db.Sections
其中i.ID == ID
选择新的SectionViewModel()
{
ID = i .ID,
SectionName = i.SectionName,
Active = i.Active,
SiteName = i.Site.SiteName
})。FirstOrDefault();
}
ADDED:
创建SectionViewModel对象(它是一个View模型类):
public ActionResult SectionForm(int?id)
{
SectionViewModel model = new SectionViewModel(id);
return View(model);
}
但当然这是不可能的,因为这个只能用于阅读。任何方式来做?
修改
OK,所以你从中构造一个
。这样做有所不同,但是我的原始答案中还有很多言论适用。 SectionViewModel
而不是一个 Section
节
一个更好的方法是
public ActionResult SectionForm(int id)
{
Section section = this._context.Sections.Find(id);
SectionViewModel model = .... //映射代码
return View(model);
}
这部分 //映射代码
可以将属性从部分
复制到模型
中。您可以使用AutoMapper。
在 SectionViewModel
的构造函数中不这样做的原因是不应该首先是一个静态的上下文。您可以创建和处理上下文。但是谁说, SectionViewModel
总是单独构建?也许在另一种方法你会返回一个列表。单独创建每个模型将是非常低效的。 AutoMapper的 Project()。到
方法将适用于此。 / p>
原始文本
在构造函数中构造一个对象(这是零件 var s =(...)。FirstOrDefault()
)发生的荒谬,然后将其属性复制到所有者的构造函数,它是相同的类型, Section
。更糟糕的是,在您的查询中,您也从一个部分构造一个 Section
。所以运行语句后...
Section model = new Section(id);
...您已经构建了三个相同的 Section
其中最后一个最终被使用:
第1节:$ code从我在_db.Sections其中i.ID == ID选择我。
第2节:选择新的Section(){...}
第3节: Section(int ID)
而EF甚至不允许像
从我在_db.Sections
/ pre>
中选择新的Section(){...}
它会告诉你,你不能在LINQ到实体查询中构造一个实体。
但是删除这个
选择新的Section(){...}
甚至不是声音重构的开始。整个构造是荒谬的。
另一个不好的做法是有静态上下文。上下文设计为具有较短的使用寿命,因为它们缓存从数据库中获取的每个实体。一个静态上下文是一个内存泄漏。
实现你想要的方式是简单的...
public ActionResult SectionForm(int id)
{
Section model = this._context.Sections.Find(id);
return View(model);
}
...其中
this._context
是您的VTSEntities
的一个实例,它是根据控制器实例创建的(或通过控制容器的反转注入)。
I have the following class:
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; } }
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(); }
ADDED:
Create SectionViewModel object (it's a View model class):
public ActionResult SectionForm(int? id) { SectionViewModel model = new SectionViewModel(id); return View(model); }
but, of course, it's impossible because "this" is available only for read. Any way to do it?
解决方案Edit
OK, so you construct a
SectionViewModel
, not aSection
, from aSection
. That makes some difference, but still many remarks from my original answer apply.A better way to do this is
public ActionResult SectionForm(int id) { Section section = this._context.Sections.Find(id); SectionViewModel model = .... // Mapping code return View(model); }
This part
// Mapping code
can be anything that copies properties fromsection
tomodel
. You could use AutoMapper.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 thatSectionViewModel
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'sProject().To
approach would be appropriate there.
Original text
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 aSection
from a section. So after running the statement...Section model = new Section(id);
...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
.
Section 2:select new Section() {...}
Section 3:Section(int ID)
And EF doesn't even allow a statement like
from i in _db.Sections select new Section() {...}
It will tell you that you can't construct an entity in an LINQ-to-Entities query.
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); }
...where
this._context
is an instance of yourVTSEntities
that is created per controller instance (or injected into it by an Inversion of Control container).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 aDbContext
is a UoW). It also breaks the persistance ignorance principle that EF is built on. It breaks query composability and it easily causesn + 1
queries.这篇关于容易的方法来填充对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!