.net 多态性是否干扰NHibernate';s的批插入/更新功能?

.net 多态性是否干扰NHibernate';s的批插入/更新功能?,.net,nhibernate,polymorphism,batching,.net,Nhibernate,Polymorphism,Batching,我的班级结构如下: public class Person { public virtual int Id { get; protected internal set; } public virtual string Name { get; set; } } public class Customer : Person { public virtual string AccountNumber { get; set; } } Customer被映射为Person的子类

我的班级结构如下:

public class Person
{
    public virtual int Id { get; protected internal set; }
    public virtual string Name { get; set; }
}

public class Customer : Person
{
    public virtual string AccountNumber { get; set; }
}
Customer
被映射为
Person
的子类(使用FluentNHibernate的
子类映射
),表结构是每个子类的表(单独的
Person
Customer
表共享
Id
列)

在我的测试中,我打开一个无状态会话并尝试插入一系列
Person
实体:

using (var stateless = sessionFactory.OpenStatelessSession())
using (var transaction = stateless.BeginTransaction())
{
    var persons = new[]
    {
        new Person { Name = "Alice" },
        new Person { Name = "Bob" },
        new Customer { Name = "Cathy", AccountNumber = "001" },
        new Customer { Name = "Dave", AccountNumber = "002" }
    };
    foreach (var person in persons)
        stateless.Insert(person);
    transaction.Commit();
}
如果在
ShowSql
开关打开的情况下运行此操作,我可以看到
Person
表上生成了
INSERT
语句(这意味着它们是批处理的),但是
Customer
表生成了
INSERT
语句(从中我推断,这些未被分批处理)

奇怪的是,我发现如果派生类型(即
Customer
)有自己的集合(我们称它们为
Orders
),并且我
将该集合中的每个项直接插入到相同的无状态会话中(而不是实际的集合中)这种行为似乎完全局限于多态实体的派生类

这是预期的行为吗?如果是,有没有办法重写上面的插入代码,以确保所有子类表都是批处理的


(注意:我正在对所有ID使用
SequenceHilGenerator
,并且我已经相应地配置了
ADONebatchSize
,因此,据我所知,这不是批处理的一般问题。我可以看到在批处理操作发生时命中
HiLo
表。)

经过几天的挖掘和实验,答案似乎是“是”。有人顺便提到,NHibernate在批处理子类方面有困难-特别是在使用每个子类的表时(我一直在使用)

这不是每个类的表层次结构策略的问题。不幸的是,在游戏中改变持久性模型对我来说太晚了(另外,从关系数据库设计的角度来看,我真的不喜欢TPH),所以我不得不考虑其他选项

我能够通过以下方式解决插入的问题:

  • 使基类具体化(过去是抽象的)
  • 为要插入的每个对象创建一个浅层副本(仅构建基类)
  • 照常插入副本
  • 刷新会话以满足引用完整性约束
  • 使用
    SqlBulkCopy
    将派生类插入到它们自己的表中,在将
    IClassMetadata
    强制转换为
    AbstractEntityPersister
    的基础上使用一些可怕的巫术,以获得所有列/表映射
  • 使用
    IStatelessSession.Insert
    方法正常插入子类拥有的所有映射集合(对具有自己的类层次结构的集合重复此过程)
  • 我想,如果不依赖硬编码的表/列名,更新将更加复杂,并且可能非常难以处理;如果必须这样做,我可能会依赖存储过程(带有表值参数或临时表)


    生成的代码看起来并不令人愉快,但它显著提高了性能-对于正常大小的大约20-30k的批处理,至少提高了25%。

    这一个现在让我们很头疼。我们有一个场景,每个子类的表工作得很好,但每个类的表层次结构会很混乱(另外,我们也在游戏后期)。我们最初的方法之一是使用一些手动SQL在进程外执行这些更新,但我们也遇到了一些挑战,使我们的二级缓存过期,以确保NH知道它的数据对于此对象层次结构是过时的。太令人沮丧了。我们使用的是3.3.4.4000。不确定这是否是4.x中的问题,但我没有读到任何相关信息我不这么认为。