2010-01-04 30 views
6

我有以下類:Nhibernate在選擇上進行更新?

public class Product 
{ 
    public virtual Guid Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Decimal PricePerMonth { get; set; } 
    public virtual BillingInterval DefaultBillingInterval { get; set; } 
    public virtual string AdditionalInfo { get; set; } 
} 

和映射如下所示:

<class name="Product" table="Products"> 
    <id name="Id" column="ProductId"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="Name" column="ProductName" not-null="true" type="String" /> 
    <property name="PricePerMonth" column="PricePerMonth" not-null="true" type="Decimal" /> 
    <property name="DefaultBillingInterval" type="int" not-null="true" /> 
    <property name="AdditionalInfo" type="string" not-null="false" /> 
</class> 

我使用Repository<T>類下面的方法(Session是返回當前會話的屬性):

public IEnumerable<T> FindAll(DetachedCriteria criteria) 
{ 
    return criteria.GetExecutableCriteria(Session).List<T>(); 
} 

現在,當我執行以下操作(會話是在存儲庫中使用的同一會話):

IEnumerable<ProductDTO> productDTOs = null; 
using(ITransaction tx = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
{ 
    var products = repository.FindAll(new DetachedCriteria.For<Product>().Add(Restrictions.Like("Name", "Some Product%"))); 
    productDTOs = ToDTOs(products); 
    tx.Commit(); 
} 
// Do stuff with DTO's 

commit語句在那裏,因爲我使用了一個服務層,如果沒有錯誤發生,它會自動提交每個事務。我崩潰了我的服務層在這裏更容易可視化..

ToDTOs方法簡單地轉換爲DTO:

private IEnumerable<ProductDTO> ToDTO(IEnumerable<Product> products) 
{ 
    return products.Select(x => new ProductDTO() 
    { 
     Id = x.Id, 
     Name = x.Name, 
     PricePerMonth = x.PricePerMonth, 
     AdditionalInfo = x.AdditionalInfo 
    }).ToList(); 
} 

我NHibernate的日誌顯示以下的輸出:

2010-01-04 19:13:11,140 [4] DEBUG NHibernate.SQL - SELECT ... From Products ... 
2010-01-04 19:13:11,237 [4] DEBUG NHibernate.SQL - UPDATE Products ... 
2010-01-04 19:13:11,548 [4] DEBUG NHibernate.SQL - UPDATE Products ... 
... 

所以選擇該產品發佈會話提交時返回的每個產品的更新聲明,即使產品中沒有任何更改..

有何想法?

+0

這是*真*實體是如何實現的?我不相信你。 – 2010-01-04 18:44:15

+0

這是......的確,我有一個產品所附的訂單清單,但是我已經從類和映射中刪除了這個清單(如圖所示),並且它是相同的結果。 我的困惑是更深刻的事實,這不會發生在我的其他實體.. – 2010-01-04 18:46:44

回答

7

我只有這樣的效果,當我有一個實體沒有從屬性返回相同的值比已分配給它的值。然後它被NH視爲髒。

例子:

class Foo 
{ 
    private string name; 

    public string Name 
    { 
    // does not return null when null had been set 
    get { return name ?? "No Name"; } 
    set { name = value; } 
    } 

} 

這是我會怎麼寫映射文件。

<class name="Product" table="Products"> 
    <id name="Id" column="ProductId"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="Name" column="ProductName" not-null="true" /> 
    <property name="PricePerMonth" not-null="true" /> 
    <property name="DefaultBillingInterval" not-null="true" /> 
    <property name="AdditionalInfo" /> 
</class> 

您不需要指定類型。它們在運行時由NHibernate決定。

+0

啊哈,所以它必須是BillingInterval枚舉,導致問題,因爲它被映射爲一個int?如何在沒有更新語句的情況下映射枚舉(由int支持)? – 2010-01-04 19:18:23

+0

映射枚舉時不需要指定任何類型。 – 2010-01-04 19:26:40

+0

即使數據庫將DefaultBillingInterval作爲smallint存儲(枚舉值具有整數值3,6,12),這樣做還能工作嗎? – 2010-01-04 19:28:04

1

較早的帖子,但也許這會幫助某人在路上。我有一個Data Repository C#類庫(Oracle作爲數據庫)。表值是NULL,但在我的回購中,該值被定義爲十進制,應該是?十進制。這在運行select時解決了此更新問題。

+1

另一個可以得到意料之外的UPDATE的場景是,當一個新屬性已經被添加到數據庫映射中並且一個記錄被從使用舊版本映射創建的數據庫中讀取時。 – 2017-06-16 21:34:15

+0

詹姆斯,很高興知道! – 2017-06-16 21:49:42