2

Ich habe Tabelle pro Hierarchie Entity Data Model mit einem abstrakten Dokument Entität und mehreren abgeleiteten Einheiten (Blog, Seite, ...) implementiert. Ich habe Repository-Schnittstelle mit Methodensignaturen Document Entität wie dieseTabelle pro Hierarchie Implementierung mit Entity Framework und Repository Muster

public Document Load(Guid firmId, int prettyId) 
{ 
    // the OfType<> can be OfType<Page>, OfType<Blog>, ... 
    var instance = (from c in _ctx.Documents.OfType<X>() where c.firm_id == firmId && c.PrettyId == prettyId select c).FirstOrDefault(); 
    ... 
} 

ich mit nur einer Klasse, die das Repository implementiert und es Dokument als Typ von Methoden zurückzukehren verwendet. Ich brauche keine benutzerdefinierten Implementierungen für verschiedene Typen, die von Document abgeleitet sind, da die Implementierungsspezifikationen für das Laden, Einfügen und Aktualisieren für alle gleich sind. Ich muss nur den Typ für die Methoden identifizieren/bereitstellen, mit denen wir arbeiten möchten.

Hoffentlich werden Sie verstehen, was ich meine. Bitte antworten Sie nicht mit Referenzen darauf, wie man das TPH modelliert, weil ich das schon gemacht habe und es ist gut modelliert.

Antwort

1

Ich habe tatsächlich entdeckt, dass ich keine Laufzeiterkennung brauche, weil ich Typ zur Kompilierzeit in meinen MVC-Controllern bereitstellen kann, die im Gegensatz zum Repository (das nur eins ist) typspezifisch sind (Ich habe PageController, BlogController, etc.), wie folgt aus:

public virtual ActionResult Print(int prettyId) 
{ 
    //Document invoice = _repository.Load(prettyId, _docType); 
    Document invoice = _repository.Load<Invoice>(prettyId); 
    ... 
} 

in meinem Repository-Schnittstelle ich habe jetzt das:

// also, please comment, which one is better, this one? 
T Load<T>(int prettyId) where T : Document; 
T Load<T>(Guid firmId, int prettyId) where T : Document; 

// or this one? 
//T Load<T1>(int prettyId) where T1 : Document; 
//T Load<T1>(Guid firmId, int prettyId) where T1 : Document; 

und in Repository Implementierung habe ich diese:

public T Load<T>(int prettyId) where T : Document 
{ 
    return Load<T>(AppState.FirmId, prettyId); 
} 

public T Load<T>(Guid firmId, int prettyId) where T : Document 
{ 
    var instance = 
     (from c in _ctx.Documents.OfType<T>() 
     where c.firm_id == firmId && c.PrettyId == prettyId 
     select c).FirstOrDefault(); 
    instance.FirmReference.Load(); 
    instance.ClientReference.Load(); 
    instance.DocumentItems.Load(); 
    instance.TaxStatementReference.Load(); 
    return instance; 
} 

Das funktioniert und sieht ein bisschen nett aus.

+0

Yup, das ist was ich tue. Generika sind ein guter Fall, wenn irgendeine Art von Polymorphismus (z. B. abstrakte Klassen) verwendet wird. Was Ihre Schnittstelle betrifft, gibt es keinen Unterschied zwischen der ersten oder der zweiten (auskommentierten). Einer hat einen Typparameter/eine Einschränkung von T, der andere T1. Dies sind nur Aliase für den Typ-Parameter - sie können alles sein, macht keinen Unterschied. In Ihrem Fall würde ich sie "TDocument" nennen, um expliziter zu sein. Was die Implementierung betrifft, würde ich '.Load()' nicht für alle Typen verwenden, da die Methodensignatur dies nicht vorschreibt. Ich würde das über Erweiterungsmethoden tun. – RPM1984

+0

Oh, und gut gemacht, dies auch für sich selbst herauszufinden - +1. – RPM1984

+0

Können Sie ein Beispiel für Erweiterungsmethoden zum Referenzladen bereitstellen? – mare

0

Einfache Möglichkeit besteht darin, für jeden speziellen Dokumenttyp, den Sie laden möchten, eine separate Methode zu erstellen oder switch/case-Anweisungen mit einem Diskriminator als Parameter in der Load-Methode zu verwenden. Ich verstehe, dass Sie eine solche Lösung vermeiden möchten. In diesem Fall sollten Sie versuchen, die Reflektion zu verwenden, da die Angabe generischer Typparameter zur Laufzeit nicht möglich ist. Überprüfen Sie diese answer für den Aufruf der generischen Methode mit Reflektion. Sie rufen die Basisabfrage mit OfType auf und rufen die Instanz von IQueryalbe ab, die für den zweiten Teil der Abfrage mit where-Bedingungen verwendet wird.

Verwandte Themen