2012-06-24 50 views
-2

我想更新A N列的表格的一個N-1列僅某些列說N-1列中包含使用NHibernate QueryOver語法N列的表。更新使用QueryOver <T>()方法

我試過的查詢就是這樣的。

public T UpdatePost(Object DateUpdated, object DateExpires, object Id) 
    { 
     using (var session=sessionFactory.OpenSession()) 
     { 
      using (var transaction=session.BeginTransaction()) 
      { 
       session.Update(DateUpdated, Id); 
       session.Update(DateExpires, Id); 
       transaction.Commit(); 
       return session.Get<T>(Id); 
      } 
     } 
    } 

調用方法是

obj.UpdatePost(DateTime.Now, DateTime.Now.AddDays(30), 3); 

錯誤是

沒有您的映射問題。您可能試圖將System.ValueType映射到NHibernate不允許的地方,或者您錯誤地使用映射到的IDictionary。 ValueType(System.DateTime)不能與IdentityKey一起使用。

如何實現這一目標?

回答

2

UpdatePost方法是沒有意義的。 NHibernate的session.Update需要一個應該更新的實體對象。您嘗試使用的過載文檔是:

更新與給定標識符關聯的持久狀態。

第一參數應該是整個實體對象。

如果你試着分析你的代碼,有沒有辦法讓NHibernate的知道你想更新哪個實體。 Update方法不是通用的,也不是Session。你只是想給它一個日期值和一個id。 NHibernate如何知道哪個表和哪一列要更新?

爲了做到與NHibernate部分更新,您將需要使用HQL update queries(DML風格的操作)。

下面是它會是什麼樣子,你的情況:

public T UpdatePost(Object DateUpdated, object DateExpires, object Id) 
{ 
    using (var session=sessionFactory.OpenSession()) 
    { 
     using (var transaction=session.BeginTransaction()) 
     { 
      string hqlUpdate = 
       "update Post p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id"; 
      session.CreateQuery(hqlUpdate) 
        .SetDateTime("dateUpdated", DateUpdated) 
        .SetDateTime("dateExpires", DateExpires) 
        .SetParameter("id", Id) 
        .ExecuteUpdate(); 
      transaction.Commit(); 
      return session.Get<T>(Id); 
     } 
    } 
} 

在一個側面說明,因爲你已經更新後得到實體本身,你可以簡單地先加載實體,改變其屬性和保存。你仍然有兩個數據庫操作。

public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id) 
{ 
    using (var session=sessionFactory.OpenSession()) 
    { 
     using (var transaction=session.BeginTransaction()) 
     { 
      T post = session.Get<T>(Id); 
      post.DateUpdated = DateUpdated; 
      post.DateExpires = DateExpires; 
      session.Update(post); 
      transaction.Commit(); 
      return post; 
     } 
    } 
} 

如果你真的強制NHibernate的只更新被改變的列,您可以指定動態更新的class mapping declaration =「真」。

動態更新(可選,默認爲false):指定用於UPDATE的SQL將會在運行時產生並且只包含那些改變過的那些列。

+0

嗨米羅斯拉夫,SetDateTime方法不接受對象作爲參數值,因爲我們是路過DateUpdated,DateExpires.'public牛逼UpdatePost(對象DateUpdated,對象DateExpires,對象ID)'但是我聲明瞭該方法一般我們必須提供實體的類型。您的第二個解決方案適用於實體特定的存儲庫。請查看我的答案,解決方法是在找了幾個小時後找到的。 – viento

+0

啊,好的...你可能試過用'.SetParameter()'代替。 –

0

這將是最佳解決方案,因爲SetDateTime僅接受DateTime類型作爲其參數值。在一般性地聲明這個方法的同時,我們必須根據它的實體類型來格式化查詢。

public T UpdatePost(DateTime DateUpdated, DateTime DateExpires, object Id) <-- DateTime parameters 
     { 
      using (var session = sessionFactory.OpenSession()) 
      { 
       using (var transaction = session.BeginTransaction()) 
       { 
        string hqlUpdate = string.Format(
       "update {0} p set p.DateUpdated = :dateUpdated, p.DateExpires = :dateExpires where p.id = :id", typeof(T)); <-- passing the type of the entity. 
        session.CreateQuery(hqlUpdate) 
          .SetDateTime("dateUpdated",DateUpdated) 
          .SetDateTime("dateExpires", DateExpires) 
          .SetParameter("id", Id) 
          .ExecuteUpdate(); 
        transaction.Commit(); 
        return session.Get<T>(Id); 
       } 
      } 
     } 
+0

在您的域名中,「Post」是基類嗎?不知道爲什麼該方法同時被命名爲'UpdatePost'和generic。 –

+0

帖子不是基類。這就是爲什麼我刪除了帖子並將其格式化爲typeof(T),即它對應於每個實體。在我的數據庫中,每個表(實體)都包含DateUpdated和DateExpires列。這就是爲什麼我在存儲庫級別而不是實體級別編寫Update Post方法的原因。這個功能只是更新兩次,但沒有其他列受到影響。 – viento