NHibernate-使用固定值更新多行的选定字段
如何将以下SQL查询转换为NHibernateNHibernate-使用固定值更新多行的选定字段,hibernate,nhibernate,batch-updates,Hibernate,Nhibernate,Batch Updates,如何将以下SQL查询转换为NHibernate UPDATE MyTable SET Field1 = "NewValue1", Field2 = "NewValue2" WHERE Field3 = FilterValue 假设MyTable包含大量记录,并且上面的语句会影响大量记录。它有50个字段(列),其中一些字段包含长字符串或对其他表的引用,我将避免不必要地加载/更新这些字段 我现在的实施方式如下: entities = nhSession.Qu
UPDATE MyTable
SET Field1 = "NewValue1",
Field2 = "NewValue2"
WHERE Field3 = FilterValue
假设MyTable
包含大量记录,并且上面的语句会影响大量记录。它有50个字段(列),其中一些字段包含长字符串或对其他表的引用,我将避免不必要地加载/更新这些字段
我现在的实施方式如下:
entities = nhSession.QueryOver<T>().Where(whereJunction).List();
nhSession.SetBatchSize(batchSize);
transaction = nhSession.BeginTransaction();
foreach(entity in entities)
{
//Modify entity here...
//nhSession.Update(entity);//No need to call this. Commit() will do.
}
transaction.Commit();
entities=nhSession.QueryOver().Where(whereJunction.List();
nhSession.SetBatchSize(批量大小);
事务=nhSession.BeginTransaction();
foreach(实体中的实体)
{
//在此处修改实体。。。
//nhSession.Update(entity);//无需调用此函数。Commit()即可。
}
Commit();
尽管批处理有助于提高性能,但这种方法有以下缺点:
- 执行多个语句最终会降低性能
- 长
循环foreach
- 使用
nhSession.Flush()
HQL
,出于以下原因,我不考虑这种方法:
- 弦;我不太爱他们。这就是我切换到
的原因之一ORM
- 不是强类型的。重构是困难的
- 更新不会反映在缓存中
- 我不确定这是否符合UoW(NHibernate交易)
SQL
。我想坚持下去
参考资料:
当前位置问题和所有答案都表明了我前面提到的方法
:和我上面提到的一样
:和我上面提到的一样
注意:我还添加了“hibernate”标签,假设NHibernate也提供类似的解决方案;顺便说一下,它们是双胞胎。我们必须学会使用C#(POCO)实体和强类型代码,或者使用HQL 如果我们想保持实体(映射对象)带来的舒适感,上面的代码(带问题的代码)将完成这项工作
entities = nhSession... // load and TRANSFORM to C# objects
foreach(entity in entities)
{
//Modify entity here...
}
如果我们准备好使用HQL(字符串,甚至是我们的自定义字符串生成器来实现更大程度的自动化),我们可以从NHibernate内置API中获益匪浅:
作者:Ayende
例如,如下所示:
ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
string hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";
int updatedEntities = s.CreateQuery( hqlUpdate )
.SetString( "newName", newName )
.SetString( "oldName", oldName )
.ExecuteUpdate();
tx.Commit();
session.Close();
其他您现在可以将Linq与NHibernate一起使用
//
// Summary:
// Update all entities selected by the specified query. The update operation is
// performed in the database without reading the entities out of it.
//
// Parameters:
// source:
// The query matching the entities to update.
//
// expression:
// The update setters expressed as a member initialization of updated entities,
// e.g. x => new Dog { Name = x.Name, Age = x.Age + 5 }. Unset members are ignored
// and left untouched.
//
// Type parameters:
// TSource:
// The type of the elements of source.
//
// Returns:
// The number of updated entities.
public static int Update<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, TSource>> expression);
//
//总结:
//更新指定查询选择的所有实体。更新操作已完成
//在数据库中执行,而不从中读取实体。
//
//参数:
//资料来源:
//匹配要更新的实体的查询。
//
//表达方式:
//表示为已更新实体的成员初始化的更新设置器,
//例如,x=>新狗{Name=x.Name,Age=x.Age+5}。未设置的成员将被忽略
//没有动过。
//
//类型参数:
//t来源:
//源的元素的类型。
//
//返回:
//更新实体的数量。
公共静态int更新(此IQueryable源、表达式);
在你的情况下,这意味着:
session.Query<MyTable>()
.Where(i => i.Field3 == FilterValue)
.Update(i => new MyTable { Field1 = "NewValue1", Field2 = "NewValue2" });
session.Query()
.其中(i=>i.Field3==FilterValue)
.Update(i=>newmytable{Field1=“NewValue1”,Field2=“NewValue2”});
从您的代码中,session.Query()
将加载包含所有50个字段(列)的完整实体,其中一些字段包含长字符串。我说的对吗?@AmitJoshi-no就是这样,它现在只生成一个更新查询!您还可以查看执行批量删除的.Delete()。我们刚刚迁移了一个项目来使用它们,相信我,我们很高兴。