how to achieve table per concrete class when base class is abstract in fluent nhibernate?

后端 未结 2 1081
慢半拍i
慢半拍i 2021-02-08 11:00

i have the following scenario

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

public class Fir         


        
相关标签:
2条回答
  • 2021-02-08 11:34

    It caused me headache to implement the "Table per Concrete Class" inheritance strategy with an abstract base class with nhibernate automapping. But I think, I've finally found a solution and want to share it with you. I also think, it's not added to the automapping docs, because it's maybe considered as a "weak" database design.

    First here are some resources I found about this topic:

    • https://www.codeproject.com/Articles/232034/Inheritance-mapping-strategies-in-Fluent-Nhibernat Example implementation of inheritance strategies in fluent nhibernate (!automapping).
    • https://github.com/jagregory/fluent-nhibernate/wiki/Automapping-inheritance Documentation of inheritance strategies in fluent nhibernate with automapping.
    • (can't add another link) https : // github . com /jagregory/fluent-nhibernate/pull/25/commits/2984c8c4e89aa4cec8625538f763c5931121a4e7 Bug-Fix Union-SubClass implementation (Table per Concrete Class)

    These resources basically describe how you need to do it:

    1. As you already mentioned fluent nhibernate ignores abstract base classes. So you need to add them explicitly.
    // abstractBaseTypes is just a simple enumeration of base types
    // model is the AutoPersistenceModel
    abstractBaseTypes.ForEach(m => model = model.IncludeBase(m));
    
    1. a) If you know the abstract base types at compile time you can use
    //sets the union subclass strategy for the known base model
    model.Override<SuperType>(m => m.UseUnionSubclassForInheritanceMapping()))
    
    1. b) If you don't know the concrete types you can create a mapping override for each base type:
    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));
    
    0 讨论(0)
  • 2021-02-08 11:41

    Since I haven't seen your mapping, let me provide mine. You could achieve this by doing like this

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题