2012-03-27 16 views
7

Ho implementato EF 4 nel progetto. Al suo interno, ci sono tavoli cliente e ordine. Quale ha relazione uno (cliente) a molti (ordine).come progettare ViewModel

Sto creando un viewmodel per entrambi (CustomerViewModel e OrderViewModel) da passare dal mio livello di dominio al livello di interfaccia (MVC in questo caso).

Ora la domanda è "ho bisogno di fare riferimento sia viewmodel? Per esempio in customerviewmodel ha IEnumerable<OrderViewModel> e in orderviewmodel ha CustomerViewModel. Se sì, come faccio a progettare (come una best practice) in modo che IEnumerable<OrderViewModel> e CustomerViewModel è popolata con il riferimento corretto?

+0

Vedere se questo aiuta: http://blogs.teamb.com/craigstuntz/2009/12/31/38500/ –

+0

scusa non pertinente .. – user384080

risposta

23

Guiderei sempre la progettazione di ViewModels tenendo conto della vista specifica, mai dal punto di vista del modello di dominio (= le entità) .Qualsiasi aspetto di ViewModel dipende da ciò che si desidera visualizzare e si desidera modificare in una vista

Di conseguenza non si dispone di THE OrderViewModel e THE CustomerViewModel perché hai diverse visualizzazioni che visualizzeranno o modificheranno un ordine o un cliente o parti di questi. Quindi, hai quei ViewModels per uno scopo specifico e la vista e quindi più volte in diverse varianti.

Supponiamo, si dispone di un OrderEditView e questa vista consentirà di modificare le informazioni dell'ordine e visualizzare il cliente di tale ordine. Si avrebbe un OrderEditViewModel come questo:

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; } 
    // ... 
} 

Questo OrderEditCustomerViewModel non ha bisogno di un riferimento al OrderEditViewModel.

È possibile popolare questo ViewModel in questo modo:

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(); 

D'altra parte, se si dispone di un CustomerEditView che consente di modifica delle informazioni del cliente e visualizza gli ordini del cliente in una lista, il ViewModel potrebbe essere:

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; } 
    // ... 
} 

Qui CustomerEditOrderViewModel non ha bisogno di un riferimento al CustomerEditViewModel ed è possibile creare il ViewModel dal database in questo modo, ad esempio:

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(); 

Le Customer(*)ViewModel s ei Order(*)ViewModel s sono diversi - per quanto riguarda i riferimenti necessari, le proprietà e le annotazioni di dati, a seconda della visualizzazione in cui vengono utilizzati.

Con queste considerazioni in mente, la domanda di riferimenti reciproci tra OrderViewModel e CustomerViewModel scompare perché normalmente non è necessario un riferimento bidirezionale per le proprie visualizzazioni.

+0

Slauma .. Come si fa il mapping tra viewmodel all'entità EF e viceversa? – user384080

+0

anche .. come si popola pubblico IEnumerable Orders {get; impostato; } in CustomerEditViewModel? fai pigro o bramoso? – user384080

+0

@ user384080: la mappatura dall'entità EF a ViewModel sono i due frammenti di codice con 'Select' (si chiama" proiezione "e né il caricamento lazy né ansioso, ma più vicino al caricamento avido tranne che si recuperano solo le colonne dal DB che sono davvero necessari per ViewModel, non per l'intera entità che sarebbe un sovraccarico inutile). Soprattutto l'ultimo snippet popola anche la raccolta 'Orders' (vedi il' Select' interno). Per il ritorno da ViewModel all'entità che utilizzo DTO, è possibile mappare manualmente le proprietà da ViewModel a DTO o utilizzare uno strumento come AutoMapper. – Slauma