我在项目中实现了EF 4。其中有客户和订单表。具有一个(客户)对多个(订单)的关系。
我正在为两者(CustomerViewModel和OrderViewModel)创建一个视图模型,以便从我的域层传递到接口层(本例中为MVC)。
现在的问题是"我需要同时引用两个视图模型吗?例如,在customerviewmodel中有IEnumerable<OrderViewModel>
,而在orderviewmodel中则有CustomerViewModel
。如果需要,我如何设计它(作为最佳实践),以便用正确的引用填充IEnumerable<OrderViewModel>
和CustomerViewModel
?
我总是考虑特定视图来驱动ViewModels的设计,而不是从域模型(=实体)的角度。ViewModel的外观取决于要在视图中显示的内容和要修改的内容。
因此,您没有OrderViewModel
和CustomerViewModel
,因为您有不同的视图来显示或编辑订单、客户或其中的一部分。因此,您有用于特定用途和视图的ViewModel,因此可以多次使用不同的变体。
假设您有一个OrderEditView
,该视图将允许编辑订单信息并显示该订单的客户。你会有一个像这样的OrderEditViewModel
:
public class OrderEditViewModel
{
public int OrderId { get; set; }
public DateTime? ShippingDate { get; set; }
[StringLength(500)]
public string Remark { get; set; }
//...
public OrderEditCustomerViewModel Customer { get; set; }
}
public class OrderEditCustomerViewModel
{
[ReadOnly(true)]
public string Name { get; set; }
[ReadOnly(true)]
public string City { get; set; }
// ...
}
该OrderEditCustomerViewModel
不需要对OrderEditViewModel
的引用。
您可以这样填充此ViewModel:
var orderEditViewModel = context.Orders
.Where(o => o.OrderId == 5)
.Select(o => new OrderEditViewModel
{
OrderId = o.OrderId,
ShippingDate = o.ShippingDate,
Remark = o.Remark,
Customer = new OrderEditCustomerViewModel
{
Name = o.Customer.Name,
City = o.Customer.City
}
})
.SingleOrDefault();
另一方面,如果您有一个CustomerEditView
,它允许编辑客户信息并在列表中显示客户的订单,则ViewModel可能是:
public class CustomerEditViewModel
{
public int CustomerId { get; set; }
[Required, StringLength(50)]
public string Name { get; set; }
[Required, StringLength(50)]
public string City { get; set; }
//...
public IEnumerable<CustomerEditOrderViewModel> Orders { get; set; }
}
public class CustomerEditOrderViewModel
{
[ReadOnly(true)]
public DateTime? ShippingDate { get; set; }
[ReadOnly(true)]
public string Remark { get; set; }
// ...
}
这里CustomerEditOrderViewModel
不需要引用CustomerEditViewModel
,您可以通过以下方式从数据库创建ViewModel,例如:
var customerEditViewModel = context.Customers
.Where(c => c.CustomerId == 8)
.Select(c => new CustomerEditViewModel
{
CustomerId = c.CustomerId,
Name = c.Name,
City = c.City,
Orders = c.Orders.Select(o => new CustomerEditOrderViewModel
{
ShippingDate = o.ShippingDate,
Remark = o.Remark
})
})
.SingleOrDefault();
Customer(*)ViewModel
和Order(*)ViewModel
在必要的引用、属性和数据注释方面有所不同,具体取决于使用它们的视图。
考虑到这些因素,OrderViewModel
和CustomerViewModel
之间相互正确引用的问题就消失了,因为您的视图通常不需要这样的双向引用。