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

发布于 2024-12-04 06:05:56 字数 1372 浏览 6 评论 0原文

我有以下

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 和派生类创建一个表,并且记录与 FK-PK 关系链接( 每个子类的表)。 我想要实现的是每个具体类的表。也就是说,每个派生类都有自己的表,其中包含派生类的所有属性+基类中的属性。 知道如何实现它吗?

i have the following scenario

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

for mapping i have used following code snippet :-

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

By default fluent will ignore the abstract base class that is BaseClass.
But as in the class ProcessStep there is property ContentElements which returns IList , i am getting an exception:-
NHibernate.MappingException : Association references unmapped class: BaseClass

If i include the base class using the IncludeBase(typeof(BaseClass)) then it works fine but it creates a table for BaseClass and Derived classes and the records are linked with FK-PK relationship(table per subclass).
What i want to achieve is table per concrete class. that is each derive class will have it's own table where there will all properties of derived class + properties in the base class.
Any idea how to achieve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

世界等同你 2024-12-11 06:05:56

由于我还没有看到你的地图,所以让我提供我的。你可以通过这样做来实现这一点

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

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
    }
}
凉世弥音 2024-12-11 06:05:56

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

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

这些资源基本上描述了您需要如何执行此操作:

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

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:

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文