9

tengo el siguiente escenariocómo lograr la tabla por clase concreta cuando la clase base es abstracta en nhibernate fluido?

public abstract class BaseClass 
{ 
    public virtual int Id {get; set}; 
    public virtual string Name {get; set;} 
} 

public class FirstSubClass : BaseClass 
{ 
    //properties and behaviour here 
} 

public class SecondSubClass : BaseClass 
{ 
    //properties of SecondSubclass Here 
} 

public class ProcessStep 
{ 
    public virtual IList<BaseClass> ContentElements {get; set;} 
} 

para el mapeo he utilizado este código: -

this._sessionFactory = 
          Fluently.Configure().Database(SQLiteConfiguration.Standard 
          .ConnectionString(@"Data Source=SqliteTestSqlDataAccess.s3db; Version=3; New=True; Pooling=True; Max Pool Size=1;")) 
          .Mappings(m => m.AutoMappings.Add(AutoMap.Assembly(assemblyWithDomainClasses).Conventions.Add(DefaultCascade.All()))) 
          .ExposeConfiguration(BuildSchema) 
          .BuildSessionFactory(); 

Por defecto fluidez hará caso de la clase base abstracta que es BaseClass. Pero como en la clase ProcessStep hay ContentElements propiedad que devuelve IList, me estoy haciendo una excepción: - NHibernate.MappingException: Asociación referencias de clase no asignada: BaseClass

Si incluyo la clase base utilizando el IncludeBase (typeof (BaseClass)) funciona bien, pero crea una tabla para clases BaseClass y Derivadas y los registros están vinculados con la relación FK-PK (tabla por subclase). Lo que quiero lograr es tabla por clase concreta. es decir, cada clase derivada tendrá su propia tabla en la que habrá todas las propiedades de clase derivada derivadas de la clase base. ¿Alguna idea de cómo lograrlo?

Respuesta

9

Como no he visto su mapeo, permítame proporcionar el mío. Se podría lograr esto haciendo como esto

public class BaseClassMap:ClassMap<BaseClass> 
{ 
    public BaseClassMap() 
    { 
     /* 
     * Identity generator can't be native because subclass objects should be unique 
     * So use HiLo or Guid or other generators which will generate unique id on the child tables 
     */ 
     Id(x => x.Id).GeneratedBy.Guid(); 
     Map(x => x.Name); 
     UseUnionSubclassForInheritanceMapping(); // This is important - uses union-subclass mappings for the derived classes 
    } 
} 

public class FirstSubClassMap : SubclassMap<FirstSubClass> 
{ 
    public FirstSubClassMap() 
    { 
     Table("FirstSubClassTable"); 
     // Map properties for FirstSubClass 
    } 
} 

public class SecondSubClassMap : SubclassMap<SecondSubClass> 
{ 
    public SecondSubClassMap() 
    { 
     Table("SecondSubClassTable"); 
     // Map properties for SecondSubClass 
    } 
} 
+1

estoy usando Automatizando así que no tengo ninguna disposición para mapear las clases por separado. – Niraj

+0

puede mezclar automatización con asignaciones personalizadas, para que pueda proporcionar la asignación solo para clases específicas, el resto de las clases se pueden asignar utilizando la automatización. Algo como esto Fluently.Configure (configuración) .Mappings (cfg => {cfg.AutoMappings.Add (....); cfg..FluentMappings.AddFromAssembly (Su ensamblado de mapeo personalizado);}) – Rajeesh

0

Me hizo dolor de cabeza para poner en práctica la estrategia de heredar "Tabla por clase concreta" con una clase base abstracta con automapping nhibernate. Pero creo que finalmente encontré una solución y quiero compartirla contigo. También creo que no se agrega a los documentos de automatización, porque tal vez se considere como un diseño de base de datos "débil".

Primera aquí hay algunos recursos que he encontrado acerca de este tema: aplicación

Estos recursos básicamente describe cómo tiene que hacerlo:

  1. Como ya mencionaste, el nhibernate fluido ignora las clases base abstractas. Entonces necesita agregarlos explícitamente.
// abstractBaseTypes is just a simple enumeration of base types 
// model is the AutoPersistenceModel 
abstractBaseTypes.ForEach(m => model = model.IncludeBase(m)); 
  1. a) Si conoce los tipos base abstractas en tiempo de compilación puede utilizar
//sets the union subclass strategy for the known base model 
model.Override<SuperType>(m => m.UseUnionSubclassForInheritanceMapping())) 
  1. b) Si no conoce los tipos de hormigón puede crear una anulación asignación para cada tipo de base:
public class AbstractRightEntryMappingOverride : IAutoMappingOverride<AbstractRightEntry> 
{ 
    public void Override(AutoMapping<AbstractRightEntry> mapping) 
    { 
     mapping.UseUnionSubclassForInheritanceMapping(); 
    } 
} 

// You need to tell nhibernate where to find the overriden mappings. 
// You simply can add the assemblies again. 
modelAssemblies.ForEach(a => model = model.UseOverridesFromAssembly(a)); 
Cuestiones relacionadas