2011-06-11 69 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