2016-12-02 65 views
1

如何將下列SQL查詢轉換爲NHibernate?NHibernate - 使用固定值更新多行的選定字段

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

即使配料有助於提高性能,這種方法有以下缺點:

  • 執行最終降低性能多個語句。
  • foreach循環。
  • 使用nhSession.Flush()沒有克服缺點。

優點是,更新反映在緩存中。

另一種方式是,我不考慮以下原因HQL

  • 字符串;我不太喜歡他們。這是我切換到ORM的原因之一。
  • 不是強類型。重構是困難的。
  • 更新未反映在緩存中。
  • 我不確定這是否授予UoW(NHibernate Transaction)。

另一種方法是我不想使用的原始SQL。我想堅持使用ORM。

參考文獻:

Link1:問題和所有答案提示我上面已經提到的方式。

Link2:和我上面已經提到的一樣。

Link3:和上面已經提到的一樣。

注意:我還添加了'hibernate'標籤,假設類似的解決方案也可用於NHibernate;順便說一句,他們是雙胞胎。

回答

1

我們必須選擇使用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

正如例如在此示出:

我們能做的更新,而無需裝載這樣

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

+0

我選擇使用自定義字符串生成自動化建設HQL。謝謝。 –

+0

我們做同樣的事情。它是簡單的有效的..好運與NHibernate;) –

1

現在,您可以使用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" }); 
+0

從您的代碼,'session.Query ()'將加載完整的實體與所有50個字段(列),其中一些持有長字符串。我對嗎? –

+0

@AmitJoshi這不是事情,它現在生成一個更新查詢! 您還可以查看批量刪除的.Delete()。 我們剛剛遷移了一個項目來使用這些項目並相信我我們很高興。 –

+0

謝謝,我會檢查 –