我一直在寻找一种方法,将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中吗?这是怎么做到的?
答案 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()
以映射其他字段。
永远,永远,不断地问这样的问题,你会做得很好。