2013-05-17 9 views
5

Scenario: Sto scrivendo un programma che gestisce la generazione di report.Devo usare modelli separati per dominio ed EF?

Ho il report memorizzato in un database, mappato su un modello EF. Esistono alcuni campi non di database (ad esempio alcuni campi vengono calcolati automaticamente in base agli altri campi presenti nel db). Avrebbe senso avere una classe che si mappasse esclusivamente al DB, e un'altra classe che prendesse quell'informazione e in aggiunta avesse gli altri campi di calcolo?

cioè una classe di esempio per interagire con il database codefirst sarebbe

public class Report{ 
    public int CategoryOneSeverity {get; set;} 
    public int CategoryTwoSeverity {get;set;} 
    public string Title {get;set;} 
} 

Avrebbe senso per fare un'altra classe, come:

public class ReportModel{ 
    public int CategoryOneSeverity; 
    public int CategoryTwoSeverity; 
    public string Title; 

    public int RiskRating{ 
     get{ return CategoryOneSeverity + CategoryTwoSeverity; } 
    } 
}  

O dovrebbe la proprietà RiskRating essere in EF modello.

+0

Sono d'accordo con la risposta accettata che dovreste avere classi separate: una per modellare l'archivio dati e una per modellare il vostro dominio aziendale. Tuttavia, la tua seconda classe viola diversi assiomi di buon design, il più ovvio dei quali è che i campi non dovrebbero essere esposti pubblicamente. –

+0

Non mi piace davvero inserire membri privati ​​e quindi utilizzare una proprietà per ottenerlo. un campo non ha più senso, specialmente per le aree che dovrebbero cambiare? Ad esempio, l'utente può modificare il titolo in qualsiasi momento. – appsecguy

+1

No, in realtà, non ha senso e, come ho detto, vola di fronte al buon design.La proprietà consente di aggiungere la logica di convalida, modificare la rappresentazione del campo di supporto con una conversione e, in ultima analisi, consentire all'utente di mantenere una superficie di consumo stabile. Che il nostro buon amico Jon Skeet lo dica meglio: http://www.csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx –

risposta

4

Sì, credo assolutamente che dovresti avere classi diverse per modellare il tuo dominio rispetto al tuo DB. A meno che la tua applicazione non sia banale, se provi a mappare direttamente gli oggetti del tuo dominio, devi sempre modificarli per far corrispondere a ciò che ti serve la tua struttura dati, ed eventualmente esporre cose che non vuoi esporre. Consideralo come una violazione del principio di Responsabilità Unica; la tua classe ha due ragioni per cambiare se la fai diventare oggetto di dominio e mapparla direttamente. Uno è in risposta alla modifica dei requisiti aziendali, l'altro è in risposta alla modifica dello schema di archiviazione dei dati.

+0

"la classe ha due motivi per cambiare se si rende il proprio oggetto dominio e mapparlo direttamente: uno è in risposta ai cambiamenti dei requisiti aziendali, l'altro è in risposta alla modifica dello schema di archiviazione dei dati". - Questo mi ha aiutato a visualizzarlo perfettamente. Grazie! – appsecguy

4

"Avrebbe senso di avere una classe che mappa unicamente al DB e un'altra classe che prende queste informazioni e ha le altre campi di calcolo in più?"

Molto probabilmente sì. Generalmente creo una nuova classe suffissa con "ViewModel" come HumanResourcesReportViewModel se la mia classe di entità fosse HumanResourcesReport.

C'è un sacco di variazioni su come usare ViewModels, e potremmo entrare in un dibattito pedante sulla terminologia, ma concettualmente, prendere la tua entità e creare una nuova classe con quei dati più qualsiasi informazione aggiuntiva necessaria per elaborare il report. In questo caso la generazione del report è in un certo senso la vista del modello MVC, quindi non penso che sia offensivo chiamare la classe che detiene i dati come ViewModel.

+0

Penso che tu stia parlando dell'altra estremità dell'architettura; cioè l'interfaccia utente. I ViewModels sono utilizzati nell'interfaccia utente; è per questo che sono chiamati modelli 'View'. –

+1

@Robert La generazione del report è alla fine della vista. Si ottengono i dati dal database, lo si forma in un ViewModel, quindi si genera un report che rappresenta la presentazione dei dati. Che sia generato tramite un motore di report o un motore html, è una vista. Puoi chiamarlo con qualsiasi cosa tu stia bene, ma concettualmente è la stessa cosa. Hai bisogno di alcuni dati extra che non fanno parte dell'entità. – AaronLS

+0

Ah, capisco cosa intendi. Il calcolo del RiskRating è una funzione * display *. –

4

Stai utilizzando il codice prima di DB First?

È possibile avere campi calcolati automaticamente nel modello, che non sono mappati ai campi nel database.

Dipende anche dalla tua architettura. Se si utilizza DB per la prima volta, l'aggiornamento del modello EF aggiornerà le classi EF, perdendo i campi associati. Nello scenario DB-First, un'alternativa sarebbe utilizzare la classe del modello EF come classe base e ereditarla per la classe del report.

public class ReportModel 
{ 
public int CategoryOneSeverity; 
public int CategoryTwoSeverity; 
public string Title; 
} 

public class ReportClass : ReportModel 
{ 
public int RiskRating 
{ 
get{ return CategoryOneSeverity + CategoryTwoSeverity; } 
} 
} 
+0

Questo funziona abbastanza male in tutto, ma la più banale delle applicazioni. – Andy

+0

+1 Puoi anche aggiungere proprietà direttamente alla tua classe ReportModel e taggarle con l'attributo '[NotMapped]'. Ti salva una classe extra, ma d'altra parte ingombra la tua classe di entità con proprietà che potresti non usare spesso. Quindi è un po 'un giudizio su quale strada si va. – AaronLS

+0

Andy: Non c'erano molte informazioni da seguire e intendevano mostrare cosa si poteva ottenere, con le informazioni fornite, piuttosto che una soluzione pienamente funzionante. –