使用MVC从多个领域模型中创建一个视图模型

3

我一直在寻找一种方法将两个远程相关的领域模型合并为一个视图模型,但没有成功。

我正在处理一个现有的应用程序,并被要求在传真日志搜索结果中添加一个字段。我的控制器返回一个viewModel,我只想向其中添加一个额外的字段。听起来应该是一个很容易的任务。

背景信息:

这是原始的viewModel:

public class VOEIFaxLogSearchListViewModel
{
    public DateTime DateTimeAdded { get; set; }
    public string Processor { get; set; }
    public string FaxStatusCode { get; set; }
    public string VendorOrderID { get; set; }
    public string FromFaxNumber { get; set; }
}

我想要向这个视图模型中添加一个额外的字段:

    public string CustomerName { get; set; }

应用程序设计的方式是调用存储过程来返回搜索结果的数据集。(我不会提到搜索方法(GetFaxLogSearchResult)或其SQL调用,因为这并不必要)
var resultFaxDS = vOEIDAO.GetFaxLogSearchResult(startDate,endDate,userName,faxType);

然后将生成的 DataSet 转换为 DataTable。

DataTable faxTable = resultFaxDS.Tables[0];

For循环遍历每个结果记录并将它们放入一个名为FaxModel的领域模型中。该模型通过Automapper映射到名为FaxLogSearchListViewModel的viewModel中。

for (int i=0; i<faxTable.Rows.Count;i++)
            {
                var row = faxTable.Rows[i];
                var faxLogModel = vOEIDAO.DRToFaxModel(row);

                faxViewModel.Add(Mapper.Map<FaxModel,FaxLogSearchListViewModel>(faxLogModel));
             }
        }

  return faxViewModel;
    }

以下是我所做的工作,以添加此结果字段为例:

1)向视图模型添加新属性。

2)修改检索结果的存储过程,以便在数据集中返回客户名称。

困境:

将数据集的每一行添加到域模型(DRToFaxModel)的方法正在执行这个操作...它正在填充域模型(FaxModel)。我想要添加的字段不在域模型中。 因此,如果该字段不属于具体类别,我不想向域模型添加字段。

以下是域模型和用于从搜索结果中填充每一行的方法:

public class FaxModel
    {
    public int FaxID { get; set; }
    public int FaxStatusID { get; set; }
    public string ToFaxNumber { get; set; }
    public string FromFaxNumber { get; set; }
    public DateTime DateTimeAdded { get; set; }
    public string FaxStatusCode { get; set; }
    public string Processor { get; set; }
    public string VendorOrderID { get; set; }
    }

public FaxModel DRToFaxModel(DataRow dr)
    {
        FaxModel voObj = new FaxModel();

        voObj.FaxID = GetVOInt(dr["FaxID"]);
        voObj.FaxStatusID = GetVOSmallInt(dr["FaxStatusID"]);
        voObj.ToFaxNumber = GetVOStr(dr["ToFaxNumber"]);
        voObj.FromFaxNumber = GetVOStr(dr["FromFaxNumber"]);
        voObj.DateTimeAdded = GetVODateTime(dr["DateTimeAdded"]);
        voObj.FaxStatusCode = GetVOStr(dr["FaxStatusCode"]);
        voObj.Processor = GetVOStr(dr["Processor"]);
        voObj.VendorOrderID = GetVOStr(dr["VendorOrderID"]);
        //Cant add CustomerName to the model without modifying the FaxModel domain model. 
        //Shouldn't do that because it is a domain model. 
        //CustomerName is in the CustomerModel domain Model
        //    voObj.CustomerName = GetVOStr(dr["CustomerName"]);

        return voObj;
    }  

目前,我的ViewModel添加了CustomerName属性,但是返回的CustomerName为null。

我的领域模型之间关系较远。在数据库中,FAX表可以通过ORDER表连接到CUSTOMER表,但只能通过另一个ORDER表进行连接。(FAX表具有orderID字段,ORDER表具有CustomerID字段)

因此,我的问题是:如何使用autoMapper将Fax领域模型映射到Customer领域模型,因为这两个领域没有任何公共字段可以建立关系,除非通过另一个表进行连接?

或者,您可以使用automapper将多个表映射到一个viewModel吗?该如何操作?

1个回答

2
这是一个非常好的问题。首先,看到有人询问正确的做法,而不仅仅是寻求快速解决方案,真是让人耳目一新。其次,提供的文档数量正是SO问题应该编写的方式。我希望我可以给予这个问题更多的赞。
话虽如此,由于您实际上在询问架构问题,因此没有具体的答案,只有意见。
以下是我的意见:
您声明sproc的结果已映射到域模型:
var resultFaxDS = vOEIDAO.GetFaxLogSearchResult(startDate,endDate,userName,faxType);

然而,您已经向存储过程添加了一个返回字段CustomerName,该字段不属于领域模型。我认为这是您遇到问题的核心。
在此有一个选择:此存储过程是否返回领域模型?
目前,我的观点是它不再代表一个领域模型,因为有了新字段,因此您不应该在将其映射到视图模型之前尝试将其映射到领域模型。您需要创建一个新的数据类型来将此结果映射到,它代表了您实际从存储过程中获取的内容,并将其映射到您的视图模型。
另一个选择是,该存储过程确实代表一个领域模型。如果是这样,您就不应该向其中添加一个不属于该模型的新字段。相反,您需要分别获取FaxModel领域对象和CustomerModel领域对象,并从两个对象组装视图模型。
这是单一职责原则的例子,意味着对象、函数、程序甚至整个程序集都应该只有一个用途。通过给您的存储过程赋予既是领域模型又不是领域模型的返回值,您给它赋予了多个用途。最好要么决定它代表一个FaxModel ,并接受需要从其他来源获取客户名称, 要么决定它返回其他内容,例如包含客户和传真信息的CustomerFaxModel,并将其用作此类方式。
回答您的技术问题,AutoMapper确实允许您在映射函数中除了源对象之外还传递现有目标对象。您可以从对象A映射目标以获取一些字段,然后将已经映射的目标与对象B的源一起再次传递到Map()中以映射其他字段。
始终始终保持像这样提问,您会做得很好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接