5
public class Order 
{ 
public int Id {get;set;} 
[DisplayName("User")] 
public long UserId { get; set; } 
[ForeignKey("UserId")] 
public virtual User User { get; set; } 
public decimal Amount { get; set; } 
} 

Con IEnumurableQuando esporre un oggetto IEnumerable invece di un ICollection?

public class User 
{ 
public int Id{get;set;} 
public virtual IEnumerable<Order> Orders { get; set; } 
} 

public User GetWithOrders() 
{ 
var myUser=UserRepository.GetByEmail("[email protected]"); 
myUser.Orders=OrderRepository.GetByUserId(myUser.Id); 
return myUser; 
} 

Con ICollection

public class User 
{ 
public int Id{get;set;} 
public virtual ICollection<Order> Orders { get; set; } 
} 

public User GetWithOrders() 
{ 
var myUser=UserRepository.GetByEmail("[email protected]"); 
return myUser; 
} 

Non ho lazy loading usando IEnumerable per una proprietà di navigazione. Pertanto, devo ottenere gli ordini per questo utente con un'altra query.

Ho una navigazione con ICollection. Quindi posso raggiungere ordini da parte dell'utente. Questo sembra fico Ma poi posso aggiungere nuovi ordini all'utente nel controller senza utilizzare il servizio o il repository.

È una sorta di manipolazione dei dati a livello di controller. È questo anti-pattern?

risposta

2

Ma [con ICollection] Posso aggiungere nuovo ordine in Controller senza utilizzare il servizio o il repository.

È significa che si può fare questo (supponendo che c'è una ViewModel per l'aggiunta di un ordine di un utente e un SaveChanges() da qualche parte):

public class UserController 
{ 
    public ActionResult AddUserOrder(AddUserOrderModel addOrder) 
    { 
     User user = User.GetByEmail(addOrder.UserEmail);   
     user.Orders.Add(addOrder.Order); 
     User.SaveChanges(); 
    } 
} 

E soprattutto che si può fare user.Orders.Add(...), allora questo è un effetto collaterale di esporre i tipi di entità dal tuo livello di servizio o repository.

Se si vuole evitare che, dovreste definire ed esporre un oggetto business che contiene i membri che si desidera esporre:

public class UserBLL 
{ 
    public int Id { get; private set; } 
    public IEnumerable<Order> Orders { get { return _orders.AsEnumerable(); } } 
    private IEnumerable<Order> _orders; 

    public UserBLL(User user) 
    { 
     Id = user.Id; 
     _orders = user.Orders;   
    } 

    public void AddOrder(Order order) 
    { 
     _orders.Add(order); 
    } 
} 
+0

In primo luogo, ho pensato anche a viewmodel. Ma non ero sicuro che potesse portare più complessità o meno. Userò i viewmodels se necessario. Grazie. –

+0

Il punto non è il viewmodel, davvero. È il BLL o il modello di dominio. Un oggetto che rappresenta il tuo caso d'uso (un utente che può avere ordini). Usalo se non vuoi esporre i tuoi modelli di dati con le loro viscere esposte. – CodeCaster

+0

Perché stai restituendo '_orders.AsEnumerable();' mentre '_orders' è già' IEnumerable '? –

1

Non c'è una vera scelta qui. ICollection è necessario da EF per controllare alcuni aspetti come i risultati di query di binding e il caricamento lazy. Usando lo standard IEnumerable, stai essenzialmente disattivando tutte queste funzionalità, ma con esso la comprensione di EF della struttura sottostante. Quando si generano migrazioni, EF non genererà tabelle di join sottostanti richieste per le relazioni M2M, chiavi esterne su tabelle correlate, ecc.

Lungo e breve, utilizzare ICollection. Mentre sei corretto che questo ti permette di aggiungere elementi semplicemente aggiungendoli alla raccolta su un'entità correlata, sans-DAL, non possono ancora essere salvato senza accesso al contesto. Se hai impostato correttamente il tuo DAL, questo è disponibile solo tramite il DAL stesso, quindi devi ancora restituire l'entità nella tua pipeline DAL per perpetuare una di queste modifiche. In altre parole, non ti preoccupare.

+0

sto usando CIO. Contesto condiviso per richiesta. Nella stessa richiesta se l'ho accettato per un altro scopo, potrebbe essere influenzato. Ma hai ragione penso di non avere alcuna azione che seleziona la query relazionale, quindi salva o modifica sulla stessa richiesta. Se lo farò, userò viewmodel che ha detto @CodeCaster. –

Problemi correlati