I don't want the MVC website to know too much about the database so I have no links between [the MVC website] and the Objects/DBContext projects
The problem I'm having with this structure is that, to show anything on the Views, the [MVC] Models need to know the properties for the data as defined in the Objects classes.
Questa è una contraddizione. Non stai intenzionalmente facendo riferimento al progetto Objects nel progetto MVC, ma ti aspetti di essere in grado di utilizzare le classi Objects (e le relative proprietà) nel progetto MVC.
È l'uno o l'altro. Non puoi avere la tua torta e mangiarla. O, più appropriatamente, non puoi non fare riferimento al tuo progetto e quindi fare riferimento alle sue classi.
Hai separato le tue entità dal tuo progetto MVC, ma non stai offrendo un sostituto. Se il tuo progetto MVC non può usare le tue entità; allora cosa dovrebbe usare?
Nota: generalmente sono preoccupato per il superingegnerizzazione. Posso essere d'accordo con i commentatori che menzionano il fatto che si stia esagerando. Ma per la tua domanda, è chiaro che vuoi questa separazione, quindi risponderò come tale.
Il tuo progetto Data non dovrebbe inviare le classi oggetto al progetto MVC, ma piuttosto DTO (che possono essere copie speculari delle classi entità, che non è intrinsecamente sbagliato da fare).
Un semplice esempio:
Nel progetto Oggetti:
public class Person
{
public string Name { get; set; }
}
Nel progetto Dati:
public class PersonDto
{
public string Name { get; set; }
}
Anche nel progetto Dati, a livello di repository:
public PersonDto GetPersonById(int personId)
{
Objects.Person person = myContext.People.Single(p => p.Id == personId);
Data.PersonDto personDto = new PersonDTO();
personDto.Name = person.Name;
return personDto;
}
In questo modo, l'oggetto Person
non lascia mai il progetto Dati. Il progetto MVC non è consapevole del fatto che Person
esiste, ma sa solo che PersonDto
esiste.
Ulteriori menzioni:
-
AutoMapper è una libreria comunemente utilizzata per automatizzare la mappatura tra un'entità e la sua classe DTO equivalente. Se le proprietà hanno lo stesso nome e tipo, è possibile che Automapper si converta molto rapidamente in automatico. Se i nomi sono diversi, è necessario specificare la mappatura, naturalmente.
- Il codice qui è strongmente semplificato a titolo di esempio.
- Nel caso in cui si desideri fare ciò, la separazione dei dati (business query logic) e DTO (cloni di entità) non ha senso. Tutti i progetti che ho visto mantengono questi due insieme, poiché sono strettamente legati tra loro
- I DTO esistono in particolare perché la classe Data esiste come livello di astrazione. Avere uno senza l'altro è un po 'sciocco.
- Hai separato il tuo DbContext dalle tue entità. Questo è un po 'diverso, c'è una distinzione significativa lì (ad esempio se si supporta sia il database che l'archiviazione di file XML con le stesse classi di entità). Tuttavia, un livello dati è generalmente inteso come un livello univoco , che pertanto dispone anche di oggetti univoci DTO.
- Personalmente, non mi piace usare i tipi restituiti dalle librerie (Oggetti) ai chiamanti esterni (MVC), in particolare perché richiede che il chiamante esterno (MVC) faccia riferimento anche alla libreria (Oggetti). Il più delle volte, doverlo fare per sconfiggere lo scopo di creare l'astrazione in primo luogo.
- Si possono fare eccezioni per le librerie che vengono utilizzate a tutti i livelli per altri scopi, ad es. utilizzando NLog se si desidera accedere a tutti i livelli dell'applicazione. Ma generalmente non restituirai gli oggetti / tipi NLog da un progetto all'altro.