将一个对象转换为另一个对象的最有效方法(从模型到ViewModel)

本文关键字:一个对象 模型 ViewModel 方法 有效 转换 | 更新日期: 2023-09-27 18:13:22

假设我有一个包含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
    }));
}

我认为这是很多代码来做这个。首先,我选择了我想要的所有字段,然后将所有字段复制到另一个对象中。

有"更直接"的方法来做同样的事情吗?

:

_context.CompleteModel.Select(x => new IndexViewModel { Field02, Field04, Field08 });

将一个对象转换为另一个对象的最有效方法(从模型到ViewModel)

您可以使用AutoMapper来减少锅炉板,这样您就不用手动复制字段值了。

如果你包含了AutoMapper NuGet包,那么你需要在启动时的某个地方为你的类配置以下内容:

Mapper.Initialize(cfg => cfg.CreateMap<CompleteModel, ViewModel>());

你可以这样做:

var results = await _context.CompleteModel.ToListAsync();
var viewModelResults = results.Select(Mapper.Map<ViewModel>).ToList();

这个包有很多配置选项,所以一定要看一下文档,看看它是否适合你的需要,如果适合的话,确定使用它的最佳方法。

在我看来,这是过度抽象和分层的缺点之一。VM包含在使用上下文(屏幕、进程等)中对应用程序有价值的数据。数据模型包含所有可能存储的相关数据。在某些情况下,你需要将两者匹配起来。

使用EF Projection只从数据库中获取您需要的数据到投影的数据模型类中(使用EF POCO层定义查询,但不存储结果数据)。

将投影的类映射到VM上,如果有一个简单的映射,使用Automapper或类似的方法。但是,除非您只是在编写CRUD屏幕,否则简单的逐个字段映射没有什么价值;通过EF从数据存储中获取的数据是原始的,可能是关系形式。VM所需的数据可能不太适合该表单(同样,除非您正在执行简单的CRUD表单),因此您需要通过编码数据存储和视图模型之间的关系来添加一些值。

我认为专注于代码行数会导致错误的方法。我认为你可以看着代码并问"它是否增加了任何价值"。如果你能把任务委托给Automapper,那就太好了;但是,如果您能够始终如一地将数据模型的任务委托给VM数据复制,那么除了添加一些验证注释之外,您的VM并没有真正发挥其作用。