NHibernate HiLo ID生成器。保存前生成ID

NHibernate HiLo ID生成器。保存前生成ID,nhibernate,Nhibernate,我试图在NHibernate中使用“adonet.batch_size”属性。现在,我正在以很高的速率跨多个会话创建实体(因此需要批量插入)。所以我要做的是创建一个缓冲区,在这里我保存这些实体,并定期将它们全部清除 但是,我在创建实体时需要ID。所以我想创建一个实体(在任何会话中),然后生成它的ID(我使用的是HiLo生成器)。然后在以后的某个时间(和其他会话),我希望刷新该缓冲区并确保这些ID不会更改 有什么办法可以这样做吗 谢谢 Guido我觉得奇怪的是,你需要许多会话来完成一项工作。通常一

我试图在NHibernate中使用“adonet.batch_size”属性。现在,我正在以很高的速率跨多个会话创建实体(因此需要批量插入)。所以我要做的是创建一个缓冲区,在这里我保存这些实体,并定期将它们全部清除

但是,我在创建实体时需要ID。所以我想创建一个实体(在任何会话中),然后生成它的ID(我使用的是HiLo生成器)。然后在以后的某个时间(和其他会话),我希望刷新该缓冲区并确保这些ID不会更改

有什么办法可以这样做吗

谢谢


Guido

我觉得奇怪的是,你需要许多会话来完成一项工作。通常一次会议就足以完成所有工作

也就是说,Hilo生成器在调用
nhSession.Save(object)
时设置实体上的id属性,而不需要往返数据库和
nhSession.Flush()
将刷新对数据库的插入

更新===========================================================================

这是我在一个特定案例中使用的方法,它在保持NHibernate兼容性的同时进行纯sql插入

//this will get the value and update the hi-lo value repository in the datastore
public static void GenerateIdentifier(object target)
{
      var targetType = target.GetType();
      var classMapping = NHibernateSessionManager.Instance.Configuration.GetClassMapping(targetType);
      var impl = NHibernateSessionManager.Instance.GetSession().GetSessionImplementation();

      var newId = classMapping.Identifier.CreateIdentifierGenerator(impl.Factory.Dialect, classMapping.Table.Catalog, classMapping.Table.Schema,
                                                              classMapping.RootClazz).Generate(impl, target);
      classMapping.IdentifierProperty.GetSetter(targetType).Set(target, newId);
}
因此,此方法采用新构造的实体,如

var myEnt = new MyEnt(); //has default identifier
GenerateIdentifier(myEnt); //now has identifier injected based on nhibernate's mapping
请注意,此调用不会将实体放置在任何类型的nhibernate托管空间中。因此,您仍然需要创建一个放置对象的位置,并对每个对象进行保存。还要注意的是,我将此函数用于纯sql插入,除非在实体映射中指定
generator=“assigned”
(这将需要一些自定义的hi-lo生成器),否则nhibernate可能需要不同的机制来持久化它

总之,您想要的是为一个对象生成一个Id,该Id将在将来的某个时间持久化。这会带来一些问题,例如处理由于回滚和提交失败而不存在的条目。此外,imo nhibernate不是用于此特定工作的工具,您不需要nhibernate来执行批量插入,除非存在一些复杂的实体逻辑,其成本太高(在开发时)无法自行实现

还请注意,这意味着您需要暂时分离的实体,但除非您在第一个会话上调用.nhSes.Save(obj)并刷新其内容,否则无法使用该实体,因此第二个会话在调用暂时对象上的Load时,数据库中会有一个与您想要实现的内容相矛盾的现有行


Imo不必担心数据库受到冲击,只需从上到下优化程序,以便能够处理卷。使用nhibernate进行插入似乎会适得其反,因为使用ado.net甚至isqlquery包装查询(使用我上面提供的方法)可以以4倍的性能实现相同的结果。

感谢Jaguar的回答,但不幸的是,我无法调用会话。另存为会话实际上非常短暂(于是脸红了)。我需要将这些实体缓冲的时间远远长于此。这并不是一件“奇怪”的事情。我有一个高容量的服务,每分钟可以收到数百个请求。所有这些请求都会生成一个“日志”实体。我不想每分钟命中数据库100次,我的意思是这就是批插入的目的。需要注意的一点是,我需要ID即使这些实体不在数据库中,它们也可以在后续请求中重复使用。回答得很好。我认为您在这里提出了一些很好的观点,我倾向于同意我正试图将NH弯曲到各种奇怪的位置。我认为ADO.net是阅读后的答案。感谢您的启发。勾选