Come visualizzare il codice Entity Framework con ASP.NET MVC da un punto di vista dell'architettura software?

3

Diciamo che sto avviando un progetto di applicazione Web che usa a) ASP.NET MVC b) Entity Framework

In termini di Software ARchitecture, correggimi se sbaglio,

-1) Posso inserire tutto il mio codice Entity Framework in una cartella DAL (Data Access Layer)?

Inoltre,

-2) Sarebbe corretto dire che il codice Entity Framework che si trova all'interno della DAL (Data Access Layer Folder) è parte del Modello in ASP.NET MVC dal punto di vista dell'architettura software?

    
posta user1338998 22.09.2015 - 16:58
fonte

3 risposte

3

In una semplice applicazione puoi usare una singola classe come entità EF, modello di dominio e modello di visualizzazione.

Nelle applicazioni più complesse tutti questi modelli sono diventati classi diverse. Ad esempio, le prime entità del codice e i modelli MVC di ASP.NET hanno annotazioni diverse ( KeyAttribute in EF, DisplayFormatAttribute in MVC) e in genere non devi mischiarle in una singola classe.

Inoltre, tutte le proprietà EF dovrebbero essere scrivibili, ma le proprietà del dominio possono essere di sola lettura. I modelli MVC possono contenere specifici SelectList , ma i modelli e le entità di dominio non dovrebbero.

Quindi, nell'applicazione complessa, hai modelli separati a livello di ciascuna applicazione (presentazione, dominio, accesso ai dati) e dovresti mappare questi modelli ai limiti del tier.

Guarda il piccolo esempio di un blog. Ogni post in un blog ha data / ora di creazione e (immagine) una categoria:

FE

[TableName("PostCategories")]
public class EfCategory
{
    public int CategoryId { get; set; }

    public string Name { get; set; }
}

public class EfPost
{
    public DateTime Created { get; set; }

    public virtual Category Category { get; set; }

    public int CategoryId { get; set; }

    . . .
}

Come vedi, Post.Created è una proprietà scrivibile e leggibile e Category ha un attributo TableName . Puoi usare queste classi nel livello dominio?

No. Innanzitutto, la proprietà data / ora di creazione è di sola lettura nel dominio, non è possibile modificarla. In secondo luogo, cosa succede se si desidera riscrivere l'accesso ai dati con NHibernate o ADO.NET? Non puoi causare che il tuo modello di dominio Category abbia l'attributo TableName .

Quindi, puoi creare modelli di dominio duplicati:

Dominio

public class DomainCategory
{
    public int Id { get; private set; }

    public string Name { get; private set; }

    public DomainCategory(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

. . .

public EfCategoryRepository : ICategoryRepository
{
    private readonly DbContextFactory dbContextFactory;

    . . .

    public CategoryRepository(DbContextFactory dbContextFactory)
    {
        this.dbContextFactory = dbContextFactory;
    }

    . . .

    public DomainCategory GetById(int id)
    {
        using (var dbContext = dbContextFactory.CreateReadOnlyContext())
        {
            var entity = dbContext.Set<EfCategory>.Single(c => c.Id == id);

            return new DomainCategory(entity.CategoryId, entity.Name);
        }
    }
}

Ora l'interfaccia del dominio ICategoryRepository che "conosce" i modelli di dominio, è implementata dalla classe di accesso ai dati EF EfCategoryRepository . Questa implementazione "conosce" i modelli EF e può mappare EF al dominio.

Dominio (continua)

public class DomainPost
{
    public DomainCategory { get; set; }

    public DateTime Created { get; private set; }

    . . .

    public DomainPost(EfCategory category, DateTime created, ...)
    {
        Category = new DomainCategory(category.CategoryId, category.Name);
        Created = created;
        . . .
    }
}

La proprietà del dominio Created è a differenza della proprietà EF di sola lettura.

Infine, se pensiamo al modello di modifica della vista (ASP.NET MVC), scopriremo che questo modello dovrebbe contenere l'elenco delle categorie e non dovrebbe contenere Created perché l'utente non può cambiarlo:

Presentazione

public MvcEditPost
{
    public int Id { get; set; }

    [Display("Category")]
    public int CategoryId { get; set; }

    public IEnumerable<SelectListItem> Categories { get; set; }
}

public ActionResult Edit(int id)
{
    var domainPost = postRepository.GetById(id);
    var modelPost = new MvcEditPost
    {
        Id = domainPost.Id,
        CategoryId = domainPost.Category.Id,
        Categories = categoryRepository.GetAll()
                                       .Select(c => new SelectListItem
                                       {
                                           Selected = c.Id == domainPost.Category.Id,
                                           Text = c.Name,
                                           Value = c.Id.ToString(),
                                       }),
    };

    return View(modelPost);
}

@model MvsEditPost
@using (Html.BeginForm("Post", "Edit", { Id = Model.Id }))
{
    @Html.DropDownListFor(m => m.CategoryId, Model.Categories)
}

Quindi, il codice di presentazione è anche "noto" sia per i modelli di presentazione che per i modelli di dominio e può mappare i primi in secondi. Questa differenziazione del modello ti consente di rendere tutti i livelli indipendenti. Più precisamente, un livello di presentazione e un livello di accesso ai dati dipendono ora da un livello di dominio. In questo modo è possibile riscrivere semplicemente l'accesso ai dati (da SQL Server a Oracle, da EF a NHibernate, da Single data-server a cloud), oppure è possibile eseguire una semplice riscrittura delle presentazioni (da MVC a desktop, da MVC a console). Non saresti in grado di farlo senza la differenziazione dei modelli.

    
risposta data 22.09.2015 - 17:31
fonte
0

Suppongo che tu stia parlando di un unico sito Web MVC asp .net

Penso che l'intenzione di Microsoft sia l'EF è la M in MVC, le tue entità sei tu modelli, le mappali in viste e le conservi in un db che viene creato automaticamente per te.

Tuttavia. Questo tende a cadere su progetti più grandi. Concettualmente EF fa parte del livello di accesso ai dati, allo stesso modo di SqlConnections e DataReader ecc. Idealmente dovresti metterlo in un repository di qualche tipo, assicurati che chiami solo stored procedure e lo nasconda ai tuoi modelli di dominio.

Ovviamente se lo fai, molte delle funzioni di risparmio di tempo di EF sono ridondanti. quindi devi fare una chiamata su dove tracciare la linea.

    
risposta data 22.09.2015 - 17:35
fonte
0

Le entità sono il modello, le query (EF) sono l'accesso ai dati.

Personalmente utilizzo il sistema a 3 livelli in cui la GUI (livello di presentazione) è il più stupido possibile, chiedendo che tutto venga eseguito dai servizi (livello BLL / business logic) che utilizza il DAL (livello di accesso ai dati) per mantenere i dati ( Sia che si tratti di SQL o di file o qualsiasi altro accesso ai dati a cui si possa pensare):

+-----+----+
| GUI |    |
+-----+ En |
| BLL | ti |
+-----+ ti |
| DAL | es |
+-----+----+

In un design semplice le tue entità saranno passate avanti e indietro da tutti questi livelli. Per progetti più complessi (che sono più flessibili, ma richiedono una maggiore digitazione), la GUI utilizzerà ViewModels, le funzioni BLL accettano e restituiscono le entità aziendali e il DAL prende e restituisce i POCO semplici.

Puoi testare il tuo design cercando di sostituire e sostituire il tuo DAL basato su EF con uno basato su Oracle e dovresti riuscire a farlo senza toccare il tuo BLL o la GUI. Allo stesso modo dovresti essere in grado di prendere la GUI e sostituirla con un'applicazione della riga di comando che ti consente di eseguire tutte le stesse operazioni senza dover scrivere molto di più delle semplici chiamate alla BLL.

Inoltre, in un'architettura orientata ai servizi, le entità non dovrebbero contenere alcuna logica, al contrario di una progettazione basata su domini.

    
risposta data 14.04.2017 - 14:53
fonte

Leggi altre domande sui tag