如何设计ViewModel

use*_*080 8 entity-framework viewmodel

我在项目中实施了EF 4.在其中,有表客户和订单.其中一个(客户)与多个(订单)有关系.

我正在为(CustomerViewModel和OrderViewModel)创建一个viewmodel,从我的域层传递到接口层(在本例中为MVC).

现在的问题是"我需要在customerviewmodel同时引用视图模型?例如已经IEnumerable<OrderViewModel>在orderviewmodel已CustomerViewModel.如果让我怎么设计它(作为最佳实践),以便IEnumerable<OrderViewModel>CustomerViewModel填充了正确的参考?

Sla*_*uma 26

我总是会考虑到特定的视图来驱动ViewModels的设计,而不是从域模型(=实体)的角度来看.ViewModel的外观取决于您要在视图中显示的内容和要修改的内容.

因此,您没有THE OrderViewModel和THE,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; }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您有一个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; }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这里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();
Run Code Online (Sandbox Code Playgroud)

Customer(*)ViewModelS和Order(*)ViewModels为不同-关于必要的参考文献中,属性和数据的注释,这取决于在那里它们被使用的视图.

考虑到这些因素的相互正确引用的问题OrderViewModelCustomerViewModel消失,因为你通常不需要为你的意见这样一个双向参考.