代码之家  ›  专栏  ›  技术社区  ›  gatapia

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

  •  2
  • gatapia  · 技术社区  · 14 年前

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

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

    有什么办法吗?

    圭多

    1 回复  |  直到 14 年前
        1
  •  5
  •   Jaguar    14 年前

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

    也就是说,Hilo生成器在调用时设置实体的id属性 nhSession.Save(object) 无需往返数据库和 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时,数据库中会有一个与您想要实现的内容相矛盾的现有行。

    我不害怕冲击数据库,只是从上到下优化程序,以便能够处理卷。如果使用ado.net甚至isqlquery包装的查询(使用上面提供的方法)可以以4倍的性能获得相同的结果,那么仅使用nhibernate进行插入似乎会适得其反