6

Parece que NHibernate no puede automatizar más de un IList de un tipo dado en una entidad.¿Cómo puedo usar la automatización fluida de NHibernate con múltiples listas del mismo tipo en una entidad?

Considere las dos entidades siguientes (basadas en el código de ejemplo Examples.FirstProject que se incluye con el código fuente de Fluiber 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; } 
} 

Parece ser un modelo de objeto perfectamente válido: cada tienda tiene varios empleados y varios empleados de administrador.

Pero cuando automatizo, las listas Staff y Managers se almacenan en la tabla Employee, todas con la misma clave foránea.

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 

El resultado neto es que cuando los datos se leen de nuevo fuera de la base de datos, tanto en las listas de personal y los directores se rellenan con cada fila de la tabla.

Esto parece un error en Automapping para mí, pero soy bastante nuevo en NHibernate en cualquier forma, y ​​todavía no conozco sus limitaciones.

En cualquier caso, ¿cómo puedo hacer que NHibernate trate las dos listas como distintas?

De ser posible, agradecería un fragmento de código de Automapping que aborde directamente el código de muestra que he proporcionado (por ejemplo, algo como "poner esta anulación exacta en la sección .Mappings de su CreateSessionFactory").

Esto se debe a que estoy familiarizado con Automapping y no estoy familiarizado con las formas antiguas de hacer las cosas, lo que significa que todavía no puedo "completar los espacios en blanco".

Pero si solo tienes tiempo para apuntarme en la dirección correcta, eso sería útil también.

Aquí está mi código CreateSessionFactory, para dar un poco de contexto:

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; 
    } 

Respuesta

5

Paul Batum respondió a mi pregunta here, y proporciona un autónomo ejemplo here (haga clic en el botón de descarga después de navegar a la página enlazada) de trabajo.

El siguiente código se copia de su respuesta. El punto clave está en la clase StoreMap al final de la lista, que establece una anulación con una cláusula Where que usa la propiedad IsManager en Employee.

Tenga en cuenta que (al menos con v. 1.0.0.594) hay un gran problema con Automapping - la clase de asignación (por ejemplo, StoreMap) no puede estar en el mismo Namespace como la clase de dominio (por ejemplo, Store)!

De lo contrario, NHibernate tirará "NHibernate.MappingException: (XmlDocument) (2,4): error de validación XML: ...", con absolutamente ninguna indicación de qué o dónde está el problema real es.

Probablemente se trata de un error que puede corregirse en versiones posteriores de 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); 
    } 


} 

Aquí está la anulación asignación para el almacén:

// 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)"); 
    } 
} 
Cuestiones relacionadas