MVC从远程相关的多个域模型创建视图模型

时间:2013-12-11 20:13:53

标签: c# asp.net-mvc asp.net-mvc-3 automapper asp.net-mvc-viewmodel

我一直在寻找一种方法,将2个远程相关的域模型加入到一个没有运气的视图模型中。

我正在处理现有应用程序,并且已要求在传真日志搜索结果中添加字段。 我的控制器正在返回一个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; }
}

我想为此viewmodel添加一个额外的字段:

    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)修改后的存储过程,它回退搜索结果,使其返回数据集中的CustomerName

困境:

将数据集的每一行添加到域模型(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属性,返回的客户名为null。

我的域名模型远非相关。 在数据库中,FAX表可以连接到CUSTOMER表,但只能通过ORDER表连接。 (FAX表有一个orderID字段,ORDER表有一个CustomerID字段)

所以我的问题是:  如何使用autoMapper将传真域模型映射到Customer域模型,因为2个域没有任何公共字段来构建关系而不加入另一个表?

或者你可以使用automapper将2个以上的表映射到1个viewModel中吗?这是怎么做到的?

1 个答案:

答案 0 :(得分:2)

这是一个很棒的问题。首先,看到有人询问正确的做某事的方式,而不仅仅是寻求快速解决方案,真是令人耳目一新。其次,提供的文件数量正是应该编写SO问题的方式。我希望我能给这个超过+1。

那就是说,既然你实质上是在问建筑问题,那​​就没有任何具体的答案,只有意见。

以下是我的意见:

您声明sproc的结果映射到域模型:

var resultFaxDS = vOEIDAO.GetFaxLogSearchResult(startDate,endDate,userName,faxType);

但是,您已向您的sproc添加了一个返回字段CustomerName,该字段不属于域模型。我认为这是你问题的核心。

这里有一个选择:这个sproc是返回域模型还是不是?

目前,我认为由于新字段,它不再代表域模型,因此在将其映射到视图模型之前,不应尝试将其映射到域模型。您需要创建一个新的数据类型来将此结果映射到,表示您实际从sproc获取的内容,并将 映射到您的视图模型。

替代选项是这个sproc实际上代表了一个域模型。如果是这种情况,则不应向其添加不属于模型的新字段。相反,您需要单独获取FaxModel域对象和CustomerModel域对象,并从两个对象组装视图模型。

这是单一责任原则的一个示例,这意味着对象,函数,程序集,heck甚至程序都应该具有一个目的。通过给你的sproc一个返回值,它既是域模型又不是域模型,你给它带来了不止一个目的。最好是确定它代表FaxModel,并接受客户名称需要来自其他来源,或者确定它返回其他内容,比如说CustomerFaxModel包含客户和传真信息,并使用它。

要回答您的技术问题,除了源对象外,AutoMapper还允许您将现有目标对象传递给地图功能。您可以从对象A映射目标以获取一些字段,然后使用对象B源将已映射的目标第二次传递给Map()以映射其他字段。

永远,永远,不断地问这样的问题,你会做得很好。