当基类在流畅的nhibernate中抽象时,如何实现每个具体类的表?

时间:2011-09-12 08:44:26

标签: nhibernate fluent-nhibernate abstract-class automapping table-per-class

我有以下情况

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

用于映射我使用了以下代码片段: -

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();

默认情况下,fluent将忽略BaseClass的抽象基类。 但是在类 ProcessStep 中有属性ContentElements返回 IList ,我得到一个例外: -  NHibernate.MappingException:关联引用未映射的类:BaseClass

如果我使用IncludeBase(typeof(BaseClass))包含基类,那么它工作正常,但它为BaseClass和Derived类创建一个表,并且记录与FK-PK关系链接(每个子类的表< /强>)。 我想要实现的是每个具体类的表。也就是说,每个派生类都有自己的表,其中将存在基类中派生类+属性的所有属性。 知道如何实现它吗?

2 个答案:

答案 0 :(得分:9)

由于我没有看到你的地图,我要提供我的。你可以通过这样做来实现这个目标

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 :(得分:1)

让我头疼的是实施&#34;每个混凝土类的表&#34;具有nhibernate自动化的抽象基类的继承策略。但我认为,我终于找到了解决方案,并希望与您分享。我也认为,它没有被添加到自动化文档中,因为它可能被认为是一个弱的&#34;数据库设计。

首先,我找到了一些关于这个主题的资源:

这些资源基本上描述了您需要如何做到这一点:

  1. 正如您已经提到的,流利的nhibernate忽略了抽象基类。所以你需要明确地添加它们。
  2. // abstractBaseTypes is just a simple enumeration of base types
    // model is the AutoPersistenceModel
    abstractBaseTypes.ForEach(m => model = model.IncludeBase(m));
    
    1. a)如果您在编译时知道抽象基类型,则可以使用
    2. //sets the union subclass strategy for the known base model
      model.Override<SuperType>(m => m.UseUnionSubclassForInheritanceMapping()))
      
      1. b)如果您不了解具体类型,可以为每种基本类型创建映射覆盖:
      2. 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));