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();

尽管批处理有助于提高性能,但这种方法有以下缺点:

优点是,更新反映在缓存中。

另一种方式是 HQL 我不考虑的原因如下:

另一种方法是原始的 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" });