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

时间:2010-07-21 02:50:54

标签: nhibernate

我正在尝试在NHibernate中使用'adonet.batch_size'属性。现在,我正在以很高的速率在多个会话中创建实体(因此批量插入)。所以我正在做的是创建一个缓冲区,我保留这些实体,并定期将它们全部冲洗掉。

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

有没有这样做?

由于

1 个答案:

答案 0 :(得分:5)

我觉得很奇怪,你需要很多会话才能做一份工作。通常,单个会话足以完成所有工作。

也就是说,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"(这将需要一些自定义高低生成器),否则nhibernate可能需要不同的机制来持久化它。

总而言之,您想要的是为将来某个时间保留的对象生成Id。这会带来一些问题,例如由于回滚和提交失败而处理不存在的条目。另外imo nhibernate不是这个特定工作的工具,你不需要nhibernate来进行批量插入,除非有一些复杂的实体逻辑太昂贵(在开发时间)你自己实现。

另请注意,您暗示您需要瞬态分离的实体,但是除非您在第一个会话上调用.nhSes.Save(obj)并刷新其内容以便第二个会话调用瞬态对象上的Load,否则无法使用它们数据库中将存在与您想要实现的内容相矛盾的行。

Imo不要害怕攻击数据库,只需优化程序从上到下以便能够处理数据。使用nhibernate进行插入似乎适得其反,当你使用ado.net甚至isqlquery包装查询(并使用我上面提供的方法)以4倍的性能获得相同的结果时