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

当基类在fluent nhibernate中是抽象的时,如何实现每个具体类的表?,nhibernate,fluent-nhibernate,abstract-class,automapping,table-per-class,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 { //pro

我有下面的场景

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;}  
}
默认情况下,fluent将忽略作为基类的抽象基类。 但是在类ProcessStep中,有返回IList的属性ContentElements,我得到一个异常:- NHibernate.MappingException:关联引用未映射的类:基类

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

由于我还没有看到您的映射,让我提供我的映射。你可以这样做

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
    }
}
public类BaseClassMap:ClassMap
{
公共BaseClassMap()
{
/*
*标识生成器不能是本机的,因为子类对象应该是唯一的
*因此,请使用HiLo或Guid或其他生成器,这些生成器将在子表上生成唯一的id
*/
Id(x=>x.Id).GeneratedBy.Guid();
Map(x=>x.Name);
UseUnionSubclass ForInheritanceMapping();//这很重要-对派生类使用union子类映射
}
}
公共类FirstSubclass映射:Subclass映射
{
公共子类映射()
{
表(“第一个子类表”);
//FirstSubClass的映射属性
}
}
公共类SecondSubclass映射:Subclass映射
{
public SecondSubClassMap()
{
表(“第二子类表”);
//第二个子类的映射属性
}
}

用带有nhibernate自动映射的抽象基类实现“每个具体类的表”继承策略让我头疼。但我想,我终于找到了一个解决方案,并想与大家分享。我还认为,它没有添加到自动映射文档中,因为它可能被认为是一种“弱”数据库设计

首先,以下是我找到的有关此主题的一些资源:

  • fluent nhibernate(!automapping)中继承策略的示例实现
  • 使用fluent nhibernate和自动映射记录继承策略
  • (无法添加其他链接)https://github。com/jagregory/fluent-nhibernate/pull/25/commissions/2984c8c4e89aa4cec8625538f763c5931121a4e7 Bug Fix Union子类实现(每个具体类的表)
这些资源基本上描述了您需要如何做到这一点:

  • 正如您已经提到的,fluent nhibernate忽略抽象基类。因此,您需要显式地添加它们
  • a) 如果您在编译时知道抽象基类型,那么可以使用
  • //为已知的基本模型设置联合子类策略
    model.Override(m=>m.UseUnionSubclass ForInheritanceMapping())
    
  • b) 如果不知道具体类型,可以为每个基本类型创建映射替代:
  • 公共类AbstractRightEntryMappingOverride:IAutoMappingOverride
    {
    公共无效替代(自动映射)
    {
    mapping.UseUnionSubclassForInheritanceMapping();
    }
    }
    //您需要告诉nhibernate哪里可以找到覆盖的映射。
    //您只需再次添加程序集即可。
    ModelAssembly.ForEach(a=>model=model.UseOverridesFromAssembly(a));
    
    我使用的是自动映射,因此我没有单独映射类的规定。您可以将自动映射与自定义映射混合使用,这样您可以仅为特定类提供映射,其余类可以使用自动映射进行映射。类似这样的流畅.Configure(configuration).Mappings(cfg=>{cfg.AutoMappings.Add(..);cfg..FluentMappings.AddFromAssembly(您的自定义映射程序集);})
    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
        }
    }
    
    // abstractBaseTypes is just a simple enumeration of base types
    // model is the AutoPersistenceModel
    abstractBaseTypes.ForEach(m => model = model.IncludeBase(m));
    
    //sets the union subclass strategy for the known base model
    model.Override<SuperType>(m => m.UseUnionSubclassForInheritanceMapping()))
    
    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));