2009-03-23 14 views
31

Sono appena passato a Fluent NHibernate e ho riscontrato un problema e non ho trovato alcuna informazione a riguardo.Fluente NHibernate, funziona con le interfacce

Qui è il caso:

public class Field : DomainObject, IField 
{ 
    public Field() 
    { 
    } 

    public virtual string Name { get; set; } 
    public virtual string ContactPerson { get; set; } 
    public virtual bool Private { get; set; } 
    public virtual IAddress Address { get; set; } 
} 

IAddress è un'interfaccia implementata da una classe denominata Indirizzo

public class Address : DomainObject, IAddress 
{ 
    public Address() 
    { 
    } 

    public virtual string City { get; set; } 
    public virtual string Country { get; set; } 
    public virtual string PostalCode { get; set; } 
    public virtual string StreetAddress { get; set; } 
} 

Ecco il mio file di mapping per entrambe le classi

INDIRIZZO

public class AddressMap : ClassMap<Address> 
{ 
    public AddressMap() 
    { 
     WithTable("Addresses"); 
     Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid(); 
     Map(x => x.City, "City"); 
     Map(x => x.Country, "Country"); 
     Map(x => x.PostalCode, "PostalCode"); 
     Map(x => x.StreetAddress, "StreetAddress"); 
    } 
} 

CAMPO

public class FieldMap : ClassMap<Field> 
{ 
    public FieldMap() 
    { 
     WithTable("Fields"); 
     Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid(); 
     Map(x => x.Name, "Name"); 
     Map(x => x.ContactPerson, "ContactPerson"); 
     Map(x => x.Private, "Private"); 
     References(x => x.Address, "AddressId").Cascade.Delete().Cascade.SaveUpdate(); 
    } 
} 

Così, quando ho provato a retrive un oggetto campo dalla mia base di dati, ottengo un errore che informa che NHibernate IAddress non è mappata. C'è un modo per specificare a NHibernate di usare la classe Address nella mappatura?

Per favore fatemi sapere se sono necessarie ulteriori informazioni.

Grazie mille,

Charles

+0

Come si modella la gerarchia di IAddress nel database? Tabella per gerarchia (una tabella che contiene tutti i tipi di indirizzo) o table-per-concrete-class? Hai detto che sei passato a Fluent, quindi pubblicare un esempio di mappatura XML potrebbe aiutare a determinare ciò che stai cercando di realizzare. –

+0

In effetti sono passato da ADO.NET Entity Framework a Nhibernate con Fluent NHibernate. Nel mio database, c'è una tabella che contiene tutti i tipi di indirizzo. A proposito, ho deciso di rimuovere quelle interfacce, ho capito che era inutile. Ma penso che la domanda sia ancora valida. Grazie, Charles –

risposta

35

Trovo che ci siano validi motivi per utilizzare un'interfaccia invece di una classe concreta come proprietà.

Ad esempio, se la classe Field era in un progetto separato per la classe Address e non si è dipesa dal progetto della classe Field dal progetto della classe Field.

Esistono altri modi per gestire questa situazione, ma il modo più semplice è spesso quello di tentare ciò che si sta facendo e spiegare esplicitamente a NHibernate la classe concreta da utilizzare per IAddress.

Ora è possibile farlo in Fluent NHibernate, in questo modo:

References(x => x.Address, "AddressId") 
    .Class(typeof(Address); 

Purtroppo si può fare questo con hasMany o HasManyToMany. Non sono sicuro che ciò sarebbe possibile anche a causa della mancanza di un valido supporto per la covarianza in C#.

+26

** Aggiornamento: ** È possibile utilizzare 'Riferimenti

(x => x.Address) .Column ("AddressId");' Si può fare lo stesso con 'hasMany' e 'HasManyToMany' aggiungendo il parametro di tipo generico. – Jay

+0

+1 per l'aggiornamento, proprio quello che stavo cercando, molte grazie. – 4imble

+0

Grazie mille, esattamente quello che stavo cercando ... provò a fare .CollectionType() incatenato al mio HasMany(), ma non sembrava funzionare. – calebt

5

Sul oggetto Campo, si ha un oggetto di tipo IAddress. Questo potrebbe essere implementato da qualsiasi numero di diverse implementazioni. Con quello che stai chiedendo, ogni implementazione avrebbe una sua mappatura, che introdurrebbe un numero qualsiasi di difficoltà (impossibilità?) Per NHibernate da gestire.

Un semplice esempio potrebbe aiutare a dimostrare. Supponiamo che tu abbia due implementazioni dell'indirizzo I indirizzo 1 e Indirizzo2. Ciascuno viene salvato nella propria tabella, tblAddress1 e tblAddress2. Quando si tenta di caricare il proprio oggetto Field, tutto ciò che NHibernate sa è che si dispone di qualcosa che implementa IAddress, non sa quale implementazione è stata mantenuta. Come saprebbe quale mappatura utilizzare per recuperare l'oggetto figlio per un dato campo?

Sono sicuro che ci sono più complicazioni, ma questo esempio mostra perché è necessario avere un mapping per il tipo esatto di oggetto che hai dichiarato.

0

Se sei interessato a disaccoppiare il tuo ORM interamente dal tuo livello dominio e le interfacce di referenziazione nel tuo livello dati invece di specificare classi concrete, puoi implementare un EmptyInterceptor per mappare tra i due.

Vedere la risposta here.

Problemi correlati