6

Sembra che NHibernate non possa automatizzare più di un IList di un determinato tipo in un'entità.Come posso utilizzare Fluent NHibernate Automapping con elenchi multipli dello stesso tipo in un'entità?

Considerare le seguenti due entità (basate sul codice di esempio Esempi.PrimaProvetta incluso con il codice sorgente di Fluent NHibernate).

public class Employee 
{ 
    public virtual int Id { get; private set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 
} 

public class Store 
{ 
    public virtual int Id { get; private set; } 
    public virtual IList<Employee> Staff { get; set; } 
    public virtual IList<Employee> Managers { get; set; } 
} 

Questo sembra essere un modello perfettamente valido oggetto - ogni negozio ha diversi dipendenti del personale e diversi dipendenti Manager.

Ma quando eseguo l'automap, gli elenchi Staff e manager sono memorizzati nella tabella Employee, tutti con la stessa chiave esterna.

Employee Table 

Id FirstName LastName Store_id 
3 Daisy  Harrison 1 
4 Jack  Torrance 1 
5 Sue  Walkters 1 
6 Tom  Tommorow 1 
7 Dick  Diggler 1 

Il risultato netto è che, quando i dati vengono letti di nuovo fuori della base di dati, sia il personale ei manager liste sono popolati con ogni riga della tabella.

Questo mi sembra un bug in Automapping per me, ma sono abbastanza nuovo in NHibernate in qualsiasi forma e non conosco ancora i suoi limiti.

In ogni caso, come posso rendere NHibernate trattare i due elenchi come distinti?

Se possibile, mi farebbe piacere un frammento di codice Automapping che affronta direttamente il codice di esempio che ho fornito (per esempio qualcosa come "mettere questo Override esatto contenuto nella sezione .Mappings del CreateSessionFactory").

Questo perché sono solo un po 'familiare con Automapping, e non conosco affatto i vecchi modi di fare le cose, il che significa che non riesco ancora a "riempire gli spazi vuoti" molto bene.

Ma se hai solo il tempo di indicarmi la direzione giusta, sarebbe utile anche.

Ecco il mio codice CreateSessionFactory, per dare un po 'di contesto:

private static ISessionFactory CreateSessionFactory() 
    { 
     ISessionFactory sessionFactory = null; 

     const string autoMapExportDir = "AutoMapExport"; 
     if(!Directory.Exists(autoMapExportDir)) 
      Directory.CreateDirectory(autoMapExportDir); 

     try 
     { 
      var autoPersistenceModel = 
       AutoMap.AssemblyOf<Product>() 
         .Where(t => t.Namespace == "Examples.FirstProject.Entities") 
         .Conventions.Add(DefaultCascade.All()) 
       ; 

      sessionFactory = Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
           .UsingFile(DbFile) 
           .ShowSql() 
         ) 
       .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
              .ExportTo(autoMapExportDir) 
         ) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory() 
       ; 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e); 
     } 

     return sessionFactory; 
    } 

risposta

5

Paul Batum risposto alla mia domanda here, e ha fornito un autonomo esempio here (fare clic sul pulsante Download dopo aver navigare alla pagina collegata) che lavorano.

Il seguente codice viene copiato dalla sua risposta. Il punto chiave è nella classe StoreMap alla fine dell'elenco, che imposta un override con una clausola Where che utilizza la proprietà IsManager in Employee.

Si noti che (almeno con v. 1.0.0.594) c'è un grande trucco con Automapping - la classe di mappatura (ad esempio StoreMap) non può essere nello stesso Namespace della classe di dominio (ad esempio Store)!

In caso contrario, NHibernate getterà "NHibernate.MappingException: (XmlDocument) (2,4): errore di convalida XML: ...", con assolutamente alcuna indicazione di cosa o dove il vero problema è.

Questo è probabilmente un bug che potrebbe essere risolto nelle versioni successive di Fluent NHibernate.

public class Employee 
{ 
    public virtual int Id { get; private set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 
    public virtual bool IsManager { get; set; } 
} 


public class Store 
{ 
    public virtual int Id { get; private set; } 
    public virtual IList<Employee> Staff { get; private set; } 
    public virtual IList<Employee> Managers { get; private set; } 


    public Store() 
    { 
     Staff = new List<Employee>(); 
     Managers = new List<Employee>(); 
    } 


    public void AddManager(Employee employee) 
    { 
     employee.IsManager = true; 
     this.Managers.Add(employee); 
    } 


    public void AddStaff(Employee employee) 
    { 
     this.Staff.Add(employee); 
    } 


} 

Ecco l'override mappatura per negozio:

// Must be in different Namespace from class Store!!! 
public class StoreMap : IAutoMappingOverride<Store> 
{ 
    public void Override(AutoMapping<Store> mapping) 
    { 
     mapping.HasMany(x => x.Managers) 
      .Cascade.All() 
      .Where("(IsManager = 1)"); 
     mapping.HasMany(x => x.Staff) 
      .Cascade.All() 
      .Where("(IsManager = 0)"); 
    } 
} 
Problemi correlati