如何正确解析复杂的视图模型来分离领域模型.净MVC

本文关键字:分离 领域模型 MVC 模型 视图 何正确 复杂 | 更新日期: 2023-09-27 18:05:09

我想知道如何解决以下情况:网站上有一个表单,管理员输入非常大量的数据到Viewmodel并传递到服务器端。

class CitizenRegistrationViewModel { 
     public string NationalPassportId { get;set; }
     public string Name { get;set; }
     public List<string> PreviousRegisteredOfficeCodes {get;set;}
     // about 30 fields like strings, Booleans, HttpBasedFiles (pdf,jpg).
}

和问题,在域这些数据需要在逻辑上分开,并存储在不同的表(类在EF)像CitizensNationalPassportsTable公民工作placerecordstable 等。有没有复杂类Citizen具有如下属性:

public class Citizen {
    public ICollection<CitizensWorkingPlaceRecords> workingPlaces
    // etc...
}

,但是这些属性分别存储在不同的表中,并且没有一对一或一对多关系(这里没有FK)。唯一的NationalPassportId属性可以用作导航键(每个用户唯一,不同表中与用户相关的所有记录都包含此键)。

我应该写大量的代码来解析Viewmodel到域模型,如:

public void CitizenRegistrationViewModelToDomainModel(CitizenRegistrationViewModel model){
    CitizenNationalPassport passport = new CitizenNationalPassport(model.NationalPassportId);
    CitizensWorkingPlaceRecord workplace = new CitizensWorkingPlaceRecord(model.PreviousRegisteredOfficeCodes, model.NationalPassportId);
     // 12 extra objects need to create...
    db.CitizenNationalPassports.Add(passport);
}
或者有没有更正确的方法来处理这个问题?我想使用AutoMapper,但它是最好的解决方案吗?我不能改变商业模式的逻辑,因为这是一个遗留项目。

如何正确解析复杂的视图模型来分离领域模型.净MVC

您应该有一组类来表示浏览器与ASP交换的数据。净MVC。例如,我们将它们命名为输入模型。在这个类中,你有元数据属性,自定义属性和许多与浏览器和web服务器之间的交换相关的东西。

你应该有另一组类代表你的数据库结构,那些是你的实体框架POCO类。我们将它们命名为DB模型。不管它们是多么的POCO和花哨,它们总是映射到表和列,所以它们总是与DB结构紧密相关。

你应该有另一组类作为你的领域类,当你在你的业务层操作对象时使用的类。它们与绑定/持久化/表示无关。

您应该有一个知道如何持久化域实体的存储库。在您的示例中,它将是一个知道如何操作DB模型和DbContext的类。

  1. 然后,当您从浏览器获得输入时,您将该数据绑定到输入模型并将其传递给控制器(这是由DefaultModelBinder自动完成的,或者您可以使用自己的IModelBinder)。
  2. 当您获得一个输入模型时,您必须使用该数据创建一个新的域实体(如果它是一个实际的新实体)。一旦您准备好了域对象,您就可以将其传递到存储库进行保存。
  3. 存储库负责知道如何使用DB模型在数据库中保存域实体。

本质上,控制器或您在控制器的操作上下文中操作的业务服务实例应该负责阐明这些元素之间的交互,而不需要它们彼此知道。

AutoMapper或其他替代方法可以用于自动从视图模型到域模型的映射,但是这只有在视图和域模型中的属性命名相同时才有意义。如果不是这样的话,你最终会写出对你没有帮助的映射规则。它只是将代码从当前的映射类移动到AutoMapper配置。所以,如果你能修改你的视图模型,我会选择AutoMapper或类似的东西,如果没有,我会使用你目前拥有的