Restituisce gli oggetti del dominio dal repository

1

Sono più esperto con l'approccio Database First per Entity Framework. Attualmente sto esaminando un progetto Code First, che restituisce oggetti del modello di dominio dal repository.

Database prima

Vedi il codice qui sotto, che è un metodo di repository Database First che ho creato:

public dbPerson getPersonByID(int personID)
        {
            return _dbContext.Set<dbPerson>()
                   .Where(x => x.ID == personID);  
        }

dbPerson è una classe creata da Entity Framework Database First. Il servizio dell'applicazione chiama getPersonByID (contenuto nel repository) e associa la classe dbPerson restituita dal repository a Person (classe Domain). L'oggetto dominio Person chiama quindi i propri metodi.

Codice prima

Ora sto guardando un'implementazione di un codice che sembra chiamare il database e restituire un oggetto di dominio, ad esempio il repository ha il seguente aspetto:

public Person getPersonByID(int personID)
        {
            return _dbContext.Set<Person>()
                   .Where(x => x.ID == personID);  
        }

In questo caso; non è necessario mappare dbPerson in Person nel servizio dell'applicazione (come nel mio esempio del Database First).

Question (s)

1) Questo è un vantaggio di Code First?

2) È un pattern anti per inserire la logica di dominio in un codice prima entità EF?

3) È un pattern anti per inserire la logica di dominio in una prima entità EF del database? Queste classi suppongono di essere trattate come semplici DTO, cioè senza metodi?

    
posta w0051977 03.08.2017 - 18:17
fonte

3 risposte

1

Dipende. La classe Person è un semplice vecchio oggetto C # quando è istanziata? Non ho molta familiarità con EF, ma in altri framework come Doctrine o Hibernate puoi fare affidamento sul framework per creare un'istanza e restituire un semplice oggetto vecchio che non contiene alcuna magia di framework.

Se questo è il caso, e non c'è nulla riguardo all'oggetto o alla classe che lo lega al framework di persistenza come una gerarchia di ereditarietà, allora sì, penso che sia perfettamente ragionevole restituirlo da un repository.

Dai commenti in basso, aggiungerei anche quanto segue. Mi rendo conto che alcune di queste idee potrebbero nuotare controcorrente un po '.

L'idea di code-first vs. db-first è fondamentalmente una reliquia inerente all'età di EF e all'evoluzione delle best practice intorno agli ORM. In particolare, con DDD, devi sempre scegliere il codice e utilizzare solo db-first quando hai un DB legacy che devi integrare con un nuovo livello dominio / applicazione. In questo senso, quando utilizzo DDD, ritengo che le classi EF db-first dovrebbero costituire l'input per il livello anti-corruzione del tuo dominio.

Tuttavia, con il paradigma code-first il problema è diverso. In questo scenario, con framework ORM come EF, non vuoi mescolare il tuo framework di persistenza con il tuo codice di dominio e quell'istinto ha perfettamente ragione.

Tuttavia solleva il problema di ciò che costituisce "mixing" e se utilizzare o meno vecchi oggetti che il framework sa come idratare dal database è sufficiente per separare le preoccupazioni. La mia opinione è che se gli oggetti idratati sono semplici vecchi oggetti che possono essere indipendenti dal framework, allora si stanno ancora separando le preoccupazioni. La ragione di ciò è che gli oggetti restituiti dai repository sono estratti dall'ORM: il codice client dei repository non può dire la differenza se il semplice oggetto vecchio proviene dall'ORM o qualche altra cosa come una fabbrica o un altro meccanismo di persistenza, come una cache.

Alcuni framework potrebbero richiedere che le tue classi code-first ereditino da una classe genitrice fornita dal framework, o potrebbero usare reflection o qualche altro dinamismo run-time per aggiungere metodi alle tue classi code-first, ad esempio per supportare un API in stile ActiveRecord. In questi casi, anche con il codice in primo luogo, direi che probabilmente è bene avere le tue classi di dominio semplici. Ma stai aggiungendo complessità per l'astrazione extra.

Alcuni framework ORM, probabilmente EF, forniranno classi di tipo proxy per entità correlate. Ad esempio, se si dispone di una classe di entità Employee che compone una classe di entità Person e sono connesse l'una con l'altra tramite una relazione di chiave esterna nel database, quando si ottiene un oggetto Employee dal repository, a seconda del tipo della query del database è stata utilizzata e la configurazione della relazione, i dati relativi all'entità Person verranno caricati pigramente dal database. In tal caso, quando si chiama getPerson () sull'oggetto Employee, viene restituito l'oggetto proxy anziché l'oggetto Persona reale e l'oggetto proxy risulterà errato nei dati Persona la prima volta che si tenta di leggere i dati dall'oggetto.

Personalmente non ritengo che l'uso di oggetti proxy in questo modo, anche se fa parte della magia del framework, dovrebbe causare la creazione di oggetti di dominio separati. Di nuovo, se dovessi scambiare gli ORM o usare un diverso archivio di persistenza, i repository potrebbero incapsulare / delegare tutto ciò. Le preoccupazioni sull'accoppiamento della struttura di persistenza e del modello di dominio possono essere alleviate nei repository.

    
risposta data 03.08.2017 - 18:57
fonte
1

Essenzialmente sono entrambi uguali. Dovresti avvolgere il tuo oggetto Person nello stesso modo in cui avvolgi il tuo dbPerson.

Sebbene sia possibile utilizzare le classi EF "POCO" per i casi più semplici, gli oggetti EF "Code First" richiederanno inevitabilmente annotazioni di dati che fanno riferimento alla libreria Entity Framework, una volta che si inizia a fare qualcosa di complicato. Questo li rende inadatti all'uso per oggetti di dominio.

Se è improbabile che tu possa spostarti da EF e non riutilizzare gli oggetti del tuo dominio in programmi che non sono in grado di fare riferimento al pacchetto EF di nuget, puoi ignorare questo problema.

Ma in realtà se si vuole restare fedeli al modello di repository in cui gli oggetti sono separati in modo netto dal database, EF è quasi inutile, si sta meglio codificando manualmente l'SQL e mappando i datareader.

    
risposta data 04.09.2017 - 23:56
fonte
0

1) Is this a benefit of Code First?

Più o meno questo è. Il vantaggio di Code-First sembra essere che il modello di dati persistente sia generato "al volo" in base alle premesse del modello di dati dell'applicazione. Quindi, un modello in meno e un codice da mantenere.

Considera il modello di dati db il modello fisico e il modello di dati di dominio il modello logico . Entrambi non sono necessariamente uguali.

Tuttavia, questo è esattamente ciò che EF Code-first fa per te. Elimina la necessità di pensare in entrambi i modelli. Il modello persistente è descritto dal modello di dati di dominio stesso, piuttosto che implementato. Quindi essenzialmente c'è un solo modello nella tua base di codice. Il modello dei dati del dominio.

Code-first segue le proprie convenzioni. Principalmente basati su configurazioni, nomi delle classi, metodi, ecc ...

Un po 'simile alla convenzione sulla configurazione.

2) Is it an anti pattern to put domain logic in a code first EF entity?

No. Proprio l'opposto. Primo codice EF ti incoraggia a concentrarti sulla logica piuttosto che sulla persistenza. Tuttavia, non ti dice come farlo. In ogni caso, potresti finire per modellare POCOS. Devi ancora avere familiarità con DDD e le sue premesse.

3) Is it an anti pattern to put domain logic in a database first EF entity?

Non necessariamente, ma è improbabile che accada. I primi database-database sono inclini a essere mappatori di riga (POCOS, DTO, qualunque cosa). Tuttavia, se hai trovato il modo per rendere le tue entità code-first "intelligenti", dovresti essere in grado di fare lo stesso con il database-first. In ultima analisi, il modello non dipende dagli strumenti che usiamo. O non dovrebbe.

La differenza tra CF e DBF è che DBF ti costringe a mappare e implementare il modello persistente, mentre CF lo fa "magicamente al volo" per te.

Un'astrazione in meno di cui preoccuparsi.

Nota: su entrambi gli approcci, i repository -CF e DBF- dovrebbero restituire entità di dominio. Seguendo CF questo è immediato, seguendo DBF ci porta ad associare il modello persistente al modello di dominio (se presente). Il livello dell'applicazione non ha bisogno di conoscere la forma dei dati sul livello di persistenza.

    
risposta data 03.08.2017 - 21:01
fonte

Leggi altre domande sui tag