3

Ich habe ein Unternehmen wie:Fluent nhibernate: Wie ordne ich eine Entität mit einer Eigenschaft zu, deren Typ eine Schnittstelle ist?

public class Employee 
{ 
    public int ID { get; set; } 
    public IAccountManager AccountManager { get; set; } 
    ... 
} 

Ich habe auch eine Zuordnung für „DefaultAccountManager“ definiert - eine konkrete Umsetzung IAccountManager. Wenn ich die obige Entität "Employee" abbilde, wie kann ich NHibernate anweisen, die AccountManager-Eigenschaft mit dem in "DefaultAccountManager" definierten Mapping beizubehalten/zu laden?

Edit: Eigentlich, wenn ich ein Setup konnte eine Zuordnung für IAccountManager so dass NHibernate nur die Implementierer zu laden/beharren, dass noch besser sein würde ableiten könnte. Ich möchte Polymorphismus lieber nicht durchbrechen, indem ich alle Implementierer zwinge, das gleiche Mapping zu verwenden.

+1

Haben Sie jemals eine Lösung für diese finden? – cbp

+0

Ah, vergaß diesen hier. Wird meine Antwort unten erklären. –

Antwort

4

Ich habe eine Antwort zu diesem gefunden. Ich bin ein wenig verschwommen auf den Details, wie es vor ein paar Monaten, aber die folgenden war der jist der Lösung:

  • eine Tabelle für jede Implementierung von IAccountManager erstellen, die Zuordnungen hat.
  • Stellen Sie sicher, dass Ihre Datenbank für die Verwendung des HiLo-ID-Algorithmus eingerichtet ist.
  • Verwenden union-Subklassen in Ihre Zuordnungen

Union-Subklassen würde wie folgt aussehen:

<class name="IAccountManager" abstract="true"> 
    <id name="ID" column="ID" type="Int32"> 
    <generator class="hilo"/> 
    </id> 
    <union-subclass name="DefaultAccountManager" table="DefaultAccountManager" 
     proxy="IAccountManager"> 
    <property name="FirstName" type="String"/> 
    <property name="LastName" type="String"/> 
    </union-subclass> 
    ... more implementations 
</class> 

Hinweis das Attribut "name" auf Union-Unterklasse. Dies sollte für jede Implementierung von IAccountManager eindeutig sein (und übereinstimmen).

Außerdem wird die ID, anstatt für jede Tabelle eindeutig zu sein, für alle IAccountManager eindeutig sein (durch Nutzung von hilo).

Wenn NHibernate eine IAccountManager-Entität erkennt, verwendet sie den konkreten Typ der Instanz und die Union-Unterklassendefinitionen, um die richtige Tabelle zu ermitteln.

Hoffe, das hilft!

0

Wenn Sie Polymorphismus benötigen, da die Funktionalität einer IAccountManager-Implementierung andere Funktionalität haben kann, können Sie discriminators betrachten und eine Basisklasse anstelle einer Schnittstelle verwenden. Wenn Sie nur eine Schnittstelle verwenden, weil sie das OOP-Paradigma du jour sind, dann denken Sie zweimal darüber nach. Entitäten, die normalerweise wenig oder kein Verhalten aufweisen, bieten in einer Situation wie dieser eine Schnittstelle wenig - wenn überhaupt - Wert .

+0

Ich habe in letzter Zeit die Schnittstellen für Entities = "no value" -Antwort gehört. Erwartet NHibernate, dass meine Entitäten nur DTOs mit anderer Logik sind? Nicht ganz zufrieden mit NHibernate, aber ich bin nur neugierig. –

+1

Nein, Ihre Entitäten müssen nicht unbedingt nur DTOs sein. Ich sagte nur, dass eine Schnittstelle nicht benötigt werden sollte, wenn es keinen Aspekt der Änderung des AccountManagers gibt, verwenden Sie keine Schnittstelle für die Verwendung einer Schnittstelle. Wenn sich in Ihrem Fall die Logik ändert, können Sie einfach eine Basisklasse anstelle einer Schnittstelle in Verbindung mit einem Diskriminator verwenden. NHibernate kann dann beim Abrufen/Speichern der Entität die korrekte Unterklasse instanziieren. Abgesehen von einem Diskriminator gibt es kein Eins-zu-eins-Mapping für eine Schnittstelle zu einem Typ, denn was ist der Zweck einer Schnittstelle? – joshperry

+0

@joshperry. Vielen Dank. Ich hatte ein fast ähnliches Problem wie das ursprüngliche Poster und versuchte genau das zu tun, was Sie nicht sagten, und ich fühlte mich nicht richtig dabei, war mir aber nicht sicher. Deine Erklärung hat mir geholfen, mich davon abzubringen. – Erick

1

Nur gedacht, ich würde einen Weg teilen, dass ich dies mit Fluent NHibernate und nicht mit den hbm-Dateien erreicht habe.

Diese Methode ist ein wenig hacky, aber die Hacks sind isoliert und leicht entfernt, sobald Fluent NH richtig Unterstützung für Union-Subclass erhält. Der Kontext meines Szenarios ist dies - die Employee-Klasse befindet sich in einem Projekt, wobei die AccountManager-Eigenschaft als Schnittstelle angegeben ist, weil sich der konkrete AccountManager in einem anderen Projekt befindet, das nicht erstellt werden soll eine Abhängigkeit zu.

Zuerst erstelle ich eine "Helper" -Klasse, die die meisten Mitarbeiter Mapping und sieht so aus.

public abstract class EmployeeMapperBase 
{ 
    protected abstract Type GetAccountManagerType(); 

    public void DoMapping(ClassMap<Employee> classMap) 
    { 
     classMap.Id(x => x.Id); 

     classMap.Maps(..... etc.... 

     classMap.References(x => x.AccountManager) 
      .Class(GetAccountManagerType()); 
    } 
} 

Als nächstes wird in dem Projekt mit der konkreten Accountmanager-Klasse, ich die Zuordnung abzuschließen:

public class EmployeeClassMap : ClassMap<Employee> 
{ 
    public EmployeeClassMap 
    { 
     new ConcreteEmployeeMapper().DoMapping(this); 
    } 

    private class ConcreteEmployeeMapper : EmployeeMapperBase 
    { 
     public override Type GetAccountManagerType() 
     { 
      return typeof(DefaultAccountManager); 
     } 
    } 
} 
+0

Ein wenig hacky, ja, aber es scheint wie eine hilfreiche Arbeit für diejenigen, die wirklich weg von XML-Mappings bleiben wollen. Persönlich sind die XML-Mappings für mich sauber und vollständig nutzbar. Andere stimmen vielleicht nicht zu. Danke für das Teilen. –

Verwandte Themen