NHibernate - 用固定值更新多行的选定字段
NHibernate - Update selected fields of multiple rows with fixed value
如何将以下 SQL 查询转换为 NHibernate?
UPDATE MyTable
SET Field1 = "NewValue1",
Field2 = "NewValue2"
WHERE Field3 = FilterValue
假设 MyTable
包含大量记录并且上述语句影响了它的很大一部分。它有 50 个字段(列),其中一些包含长字符串或对其他 table 的引用,我会避免不必要地 load/update。
我现在的实现方式如下:
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();
尽管批处理有助于提高性能,但这种方法有以下缺点:
- 执行了多个语句,最终导致性能下降。
- 长
foreach
循环。
- 使用
nhSession.Flush()
并不能克服缺点。
优点是,更新反映在缓存中。
另一种方式是 HQL
我不考虑的原因如下:
- 字符串;我不太爱他们。这就是我切换到
ORM
. 的原因之一
- 不是强类型。重构很难。
- 更新未反映在缓存中。
- 我不确定这是否符合 UoW(NHibernate 事务)。
另一种方法是原始的 SQL
,我不想使用。我想坚持使用 ORM。
参考文献:
Link1: 问题和所有答案都暗示了我上面已经提到的方式。
Link2: 和我上面已经提到的一样。
Link3: 和我上面已经提到的一样。
注意: 我还添加了 'hibernate' 标签,假设类似的解决方案也适用于 NHibernate;顺便说一句,他们是双胞胎。
我们必须选择使用 C# (POCO) 实体和强类型代码 - 或者使用 HQL。
如果我们想保持实体(映射对象)带来的舒适感 - 上面的代码(与问题一起提供)可以完成工作...
entities = nhSession... // load and TRANSFORM to C# objects
foreach(entity in entities)
{
//Modify entity here...
}
如果我们准备好使用 HQL (字符串,甚至是我们自定义的字符串构建器来使其更加自动化) 我们可以从内置的 NHibernate 中获益良多 API :
13.3. DML-style operations
NHibernate – Executable DML 来自 Ayende
例如此处显示的示例:
- Update Top n using NHibernate
我们可以在不加载任何数据的情况下进行更新
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();
其他example with delete
您现在可以将 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);
在您的情况下,这意味着:
session.Query<MyTable>()
.Where(i => i.Field3 == FilterValue)
.Update(i => new MyTable { Field1 = "NewValue1", Field2 = "NewValue2" });
如何将以下 SQL 查询转换为 NHibernate?
UPDATE MyTable
SET Field1 = "NewValue1",
Field2 = "NewValue2"
WHERE Field3 = FilterValue
假设 MyTable
包含大量记录并且上述语句影响了它的很大一部分。它有 50 个字段(列),其中一些包含长字符串或对其他 table 的引用,我会避免不必要地 load/update。
我现在的实现方式如下:
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();
尽管批处理有助于提高性能,但这种方法有以下缺点:
- 执行了多个语句,最终导致性能下降。
- 长
foreach
循环。 - 使用
nhSession.Flush()
并不能克服缺点。
优点是,更新反映在缓存中。
另一种方式是 HQL
我不考虑的原因如下:
- 字符串;我不太爱他们。这就是我切换到
ORM
. 的原因之一
- 不是强类型。重构很难。
- 更新未反映在缓存中。
- 我不确定这是否符合 UoW(NHibernate 事务)。
另一种方法是原始的 SQL
,我不想使用。我想坚持使用 ORM。
参考文献:
Link1: 问题和所有答案都暗示了我上面已经提到的方式。
Link2: 和我上面已经提到的一样。
Link3: 和我上面已经提到的一样。
注意: 我还添加了 'hibernate' 标签,假设类似的解决方案也适用于 NHibernate;顺便说一句,他们是双胞胎。
我们必须选择使用 C# (POCO) 实体和强类型代码 - 或者使用 HQL。
如果我们想保持实体(映射对象)带来的舒适感 - 上面的代码(与问题一起提供)可以完成工作...
entities = nhSession... // load and TRANSFORM to C# objects
foreach(entity in entities)
{
//Modify entity here...
}
如果我们准备好使用 HQL (字符串,甚至是我们自定义的字符串构建器来使其更加自动化) 我们可以从内置的 NHibernate 中获益良多 API :
13.3. DML-style operations
NHibernate – Executable DML 来自 Ayende
例如此处显示的示例:
- Update Top n using NHibernate
我们可以在不加载任何数据的情况下进行更新
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();
其他example with delete
您现在可以将 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);
在您的情况下,这意味着:
session.Query<MyTable>()
.Where(i => i.Field3 == FilterValue)
.Update(i => new MyTable { Field1 = "NewValue1", Field2 = "NewValue2" });