Un'applicazione ASP.NET MVC dovrebbe utilizzare direttamente Entity Framework come modello?


22

Sto costruendo la mia prima applicazione MVC in Visual Studio 2013 (MVC 5) e non sono abbastanza chiaro il modo migliore per configurare il mio modello.

Ho generato un modello di framework di entità utilizzando il codice prima di un database esistente. Il mio primo istinto è stato quello di creare alcune classi intermedie che sarebbero state il modello utilizzato dalle viste e di far funzionare quelle classi con le classi del framework di entità.

Mentre stavo scrivendo le classi intermedie, mi sono reso conto che per lo più stavo solo ri-implementando molte cose che le classi EF avevano già fatto solo con il setter privato occasionale o il cast da un tipo di dati a un altro. Quindi sembrava uno spreco.

La regola generale è utilizzare direttamente le classi del framework di entità come Modello per un'applicazione MVC? O c'è qualche vantaggio che mi manca per la costruzione di queste classi intermedie?



Se stavi usando il codice prima, allora non esisteva un database esistente, no?
Isaac Kleinman,

1
Con EF 6.1+ è possibile generare un modello in codice da un database esistente. Vedi questo articolo MSDN: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Risposte:


23

Nelle mie applicazioni ho sempre separato le cose, con diversi modelli per il database (Entity Framework) e MVC. Ho separato anche questi in diversi progetti:

  • Esempio.Entità : contiene le mie entità per EF e il contesto DB per accedervi.
  • Esempio : modelli: contiene modelli MVC.
  • Esempio : Web - Applicazione Web. Dipende da Example.Domain e Example.Models.

Invece di contenere riferimenti ad altri oggetti come fanno le entità di dominio, i modelli MVC mantengono gli ID come numeri interi.

Quando arriva una richiesta GET per una pagina, il controller MVC esegue la query del database, che restituisce un'entità. Ho scritto metodi "Converter" che prendono un'entità di dominio e la convertono in un modello MVC. Esistono altri metodi che fanno il contrario (da un modello MVC a un'entità di dominio). Il modello viene quindi passato alla vista e quindi al client.

Quando arriva una richiesta POST, il controller MVC ottiene un modello MVC. Un metodo di conversione lo converte in un'entità di dominio. Questo metodo esegue anche tutte le convalide che non possono essere espresse come attributi e si assicura che se l'entità del dominio esiste già, la stiamo aggiornando anziché ottenerne una nuova. I metodi di solito assomigliano a questo:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

Usando questi metodi prendo la duplicazione che altrimenti si verificherebbe in ciascun controller. L'uso dei generici può deduplicare ulteriormente le cose.

Fare le cose in questo modo offre molteplici vantaggi:

  • È possibile personalizzare un modello per una vista o un'azione specifica. Supponi di avere un modulo di iscrizione per una persona che, una volta inviata, crea molte entità diverse (persona, organizzazione, indirizzo). Senza modelli MVC separati questo sarà molto difficile.
  • Se devo passare più informazioni alla vista di quante sarebbero altrimenti disponibili solo nell'entità, o combinare due entità in un unico modello, i miei preziosi modelli di database non vengono mai toccati.
  • Se si serializza mai un modello MVC come JSON o XML, si ottiene solo la serializzazione immediata del modello, non tutte le altre entità collegate a questo.

Buona risposta, consiglierei di utilizzare ValueInjector o qualcosa di simile (personalmente odiavo Automapper) invece di mappare manualmente le proprietà da una classe all'altra.
Rocklan,

1
Invece di aggiungere una risposta separata, commenterò qui che nelle pratiche DDD, i tuoi "convertitori" e i modelli separati per la vista sarebbero considerati parte del livello di servizio dell'applicazione. Fondamentalmente, consente al tuo modello di dominio di essere tanto complesso quanto necessario nascondendo quella complessità dall'applicazione. Protegge anche l'applicazione da dover essere modificata a causa di una modifica nel modello di dominio. L'ASL gestisce la traduzione.
Michael Brown,

Quindi fai una chiamata per ogni modello che hai nel tuo PersonModel (cioè l'oggetto Organizzazione) per ottenere le informazioni di quel modello? Supponi di avere un modulo per aggiornare la persona e le informazioni sull'organizzazione, riceveresti una chiamata aggiuntiva quando aggiorni l'organizzazione? Sto utilizzando i processi memorizzati, quindi non posso inviare tutti gli attributi del modello e tutti gli attributi del modello contenente contemporaneamente?
Luminoso

1
Come gestiresti il ​​mapping di una raccolta? Ciò sembra essere stato molto più complicato in EF6 in quanto non è più possibile creare un nuovo elenco di entità con gli aggiornamenti in quanto ricrea solo tutto ...
Gerard Wilkinson,

2
Invece di scrivere le tue classi di convertitore, ti consiglio di usare la libreria di Automapper che è stata scritta per risolvere questo problema. È maturato molto dal 2014!
BenSmith,

6

Direi che dipende davvero dalla tua applicazione. Sta facendo semplicemente CRUD puro, senza alcuna logica aziendale? Quindi userei i modelli EF direttamente nelle mie opinioni.

Il più delle volte è coinvolta almeno una logica di business e quindi un livello tra i modelli di dati / EF e la vista potrebbe essere una buona idea. In questo caso potrebbe essere opportuno eseguire "CQRS-lite" (vedere di seguito) e utilizzare diversi modelli dentro e fuori dal controller. Il più delle volte i modelli letti sono molto più "grassi" rispetto ai modelli di scrittura ...

Tuttavia, se l'applicazione contiene molte logiche aziendali e / o deve ridimensionare molto, implementerei almeno il nucleo di essa usando CQRS (Command Query Responsibility Segregation), DDD (Domain Driven Design) e possibilmente Event Sourcing. Quindi EF potrebbe essere utilizzato come facciata del modello letto.

Ricorda inoltre che non è necessario attenersi a una strategia / modello per l'intera applicazione, alcune aree potrebbero essere CRUD puro e altre aree potrebbero contenere molta logica aziendale ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.