假设我有一个包含20个字段的模型,并且在我的索引页面中,我想列出存储在我的数据库中的所有模型。 在索引页面中,我只列出3个字段,而不是列出模型的所有字段。
所以,我做了两节课:
class CompleteModel {
public int Id { get; set; }
public string Field01 { get; set; }
public string Field02 { get; set; }
public string Field03 { get; set; }
public string Field04 { get; set; }
public string Field05 { get; set; }
...
public string Field20 { get; set; }
}
现在,在我的控制器中,我可以使用:
await _context.CompleteModel.ToListAsync();
但我觉得它似乎不是正确的方法,因为我获得了所有字段并只使用了3个字段。
所以,我制作了这段代码:
class ViewModel {
public string Field02 { get; set; }
public string Field04 { get; set; }
public string Field08 { get; set; }
}
var result = _context.CompleteModel.Select(
x => new {
x.Field02,
x.Field04,
x.Field08
}).ToListAsync();
var listResults = new List<IndexViewModel>();
if (result != null)
{
listResults.AddRange(results.Select(x => new IndexViewModel
{
Field02 = x.Field02,
Field04 = x.Field04,
Field08 = x.Field08
}));
}
我认为这要做很多代码。 首先,我选择了我想要的所有字段,然后将所有字段复制到另一个对象。
&#34;更直接&#34;如何做同样的事情?
像:
_context.CompleteModel.Select(x => new IndexViewModel { Field02, Field04, Field08 });
答案 0 :(得分:4)
您可以使用AutoMapper来减少样板,因此您不会手动复制字段值。
如果您包含AutoMapper NuGet包,那么您需要在启动时在某处为您的类配置它:
Mapper.Initialize(cfg => cfg.CreateMap<CompleteModel, ViewModel>());
然后您可以执行以下操作:
var results = await _context.CompleteModel.ToListAsync();
var viewModelResults = results.Select(Mapper.Map<ViewModel>).ToList();
该软件包有很多配置选项,因此请查看文档以确定它是否符合您的需求,并确定最佳使用方式。
答案 1 :(得分:3)
在我看来,这是过度抽象和分层的弱点之一。 VM包含在使用环境(屏幕,进程等)中对您的应用程序有价值的数据。数据模型包含可能存储的可能相关的所有数据。在某些时候你需要匹配这两者。
使用EF Projection仅将您需要的数据从数据库中提取到投影数据模型类中(使用EF POCO层定义查询,但不存储结果数据)。
如果存在naieve映射,则使用Automapper或类似方法将投影的类映射到VM上。但是,除非您只是编写CRUD屏幕,否则按字段映射的简单字段几乎没有价值;您通过EF从数据存储中获取的数据是原始的,可能是关系形式。您的VM所需的数据可能不会非常巧妙地适合该形式(再次,除非您正在执行简单的CRUD表单),因此您将需要通过编码数据存储和视图之间的关系来添加一些值模型。
我认为专注于代码行的计数会导致错误的方法。我想你可以查看那段代码并问“它是否添加了任何价值”。如果你可以将任务委托给Automapper,那就太好了;但是,如果您可以始终将数据模型的任务委托给VM数据复制,那么除了添加一些验证注释之外,您的VM并没有真正减轻其重要性。