我正在尝试在NHibernate中使用'adonet.batch_size'属性。现在,我正在以很高的速率在多个会话中创建实体(因此批量插入)。所以我正在做的是创建一个缓冲区,我保留这些实体,并定期将它们全部冲洗掉。
但是,只要我创建实体,我就需要ID。所以我想创建一个实体(在任何会话中),然后生成它的ID(我正在使用HiLo生成器)。然后在稍后(和其他会话)我想要刷新缓冲区并确保这些ID不会改变。
有没有这样做?
由于
圭
答案 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倍的性能获得相同的结果时