2011-06-11 54 views
4

我正嘗試使用EF 4.1(POCO)在Northwind數據庫的Order_Details表中執行更新。 表定義爲:使用EF更新PK時出錯

[MetadataType(typeof(Order_DetailMetadata))] 
public partial class Order_Detail 
{ 
    public int OrderID { get; set; } 
    public int ProductID { get; set; } 
    public decimal UnitPrice { get; set; } 
    public short Quantity { get; set; } 
    public float Discount { get; set; } 

    public virtual Order Order { get; set; } 
    public virtual Product Product { get; set; } 
} 

public class Order_DetailMetadata 
{ 
    [Key] 
    [Required] 
    [DisplayNameLocalized("Model_OrderDetail_OrderID_DisplayName")] 
    public int OrderID { get; set; } 

    [Key] 
    [Required] 
    [DisplayNameLocalized("Model_OrderDetail_ProductID_DisplayName")] 
    public int ProductID { get; set; } 

    [Required] 
    [Range(0.00, 9999.99, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "Model_Range_Float_Error")] 
    [DisplayNameLocalized("Model_OrderDetail_UnitPrice_DisplayName")] 
    public decimal UnitPrice { get; set; } 

    [Required] 
    [Range(1, short.MaxValue, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "Model_Range_Integer_Error")] 
    [DisplayNameLocalized("Model_OrderDetail_Quantity_DisplayName")] 
    public short Quantity { get; set; } 

    [Required] 
    [DisplayNameLocalized("Model_OrderDetail_Discount_DisplayName")] 
    [Range(0.00, 1.00, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "Model_Range_Float_Error")] 
    public float Discount { get; set; } 
} 

的問題是,當我嘗試更新與新產品的的OrderDetail項目,我得到異常:

The property 'ProductID' is part of the object's key information and cannot be modified.

的代碼是:

 int orderId = (int)detailsList.DataKeys[e.ItemIndex]["OrderID"]; 
     int productId = (int)detailsList.DataKeys[e.ItemIndex]["ProductID"]; 

     Order_Detail detail = repository.GetOrderDetail(orderId, productId); 
     detail.ProductID = int.Parse(e.NewValues["ProductID"] as string, CultureInfo.CurrentCulture); 
     detail.UnitPrice = decimal.Parse(e.NewValues["UnitPrice"] as string, CultureInfo.CurrentCulture); 
     detail.Quantity = short.Parse(e.NewValues["Quantity"] as string, CultureInfo.CurrentCulture); 
     detail.Discount = float.Parse(e.NewValues["Discount"] as string, CultureInfo.CurrentCulture); 

     repository.UpdateOrderDetail(detail); 
     repository.Save(); 

我做了一些谷歌,發現[this solution],說這樣做的一種方法是創建一個ne的新實例w產品並關聯到Order_Detail的產品導航屬性。

但這樣做,我得到另一個異常:

A referential integrity constraint violation occurred: A primary key property that is a part of referential integrity constraint cannot be changed when the dependent object is Unchanged unless it is being set to the association's principal object. The principal object must be tracked and not marked for deletion.

修改後的代碼:

 int orderId = (int)detailsList.DataKeys[e.ItemIndex]["OrderID"]; 
     int productId = (int)detailsList.DataKeys[e.ItemIndex]["ProductID"]; 
     int newProductId = int.Parse(e.NewValues["ProductID"] as string, CultureInfo.CurrentCulture); 

     Order_Detail detail = repository.GetOrderDetail(orderId, productId); 

     detail.UnitPrice = decimal.Parse(e.NewValues["UnitPrice"] as string, CultureInfo.CurrentCulture); 
     detail.Quantity = short.Parse(e.NewValues["Quantity"] as string, CultureInfo.CurrentCulture); 
     detail.Discount = float.Parse(e.NewValues["Discount"] as string, CultureInfo.CurrentCulture); 

     Product newProduct = null; 
     // the product has been changed (it is part of the PK and cannot be directly changed) 
     if (productId != newProductId) 
     { 
      // get an instance of the new product 
      newProduct = repository.GetProduct(newProductId); 
      // update the detail item with the new product instance 
      detail.Product = newProduct; 
     } 

     repository.UpdateOrderDetail(detail); 
     repository.Save(); 

我能做什麼,允許用戶更改產品的詳細資料?我真的不喜歡刪除整個記錄並用新產品重新創建它的想法。它聞起來非常糟糕!

謝謝!

回答

1

桌子設計不好。實際上,您將不得不刪除並重新添加整行。

正確的設計將有一個單獨的列作爲Order Details表(自動遞增)的主鍵。

除了您發現的限制外,該表格不支持客戶購買一個的情況,以半價獲得一個。這將需要兩個具有相同產品和訂單ID的記錄。

+2

我看到,在建模ORM框架使用的數據庫時,最好使用單個PK(標識)。但是ORM不應該是一個促進者?那麼,爲什麼這個限制?它可以用SQL中簡單的UPDATE語句解決,無需級聯。我知道,一般來說,改變一個PK值並不是一個好方法,但在這種情況下(使用一個自然鍵不需要將其他表的改變串聯起來)我看不出任何問題,對嗎?這有點令人失望。 – outlookrperson 2011-06-11 02:32:53

+0

也許這是可能的:http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/6973e314-d971-48e4-89a1-e671333dea84 – 2011-06-11 04:08:19

+0

我讀過你之前建議的鏈接,但我沒有弄清楚如何解決我的問題。 – outlookrperson 2011-06-12 12:11:55