2014-06-27 103 views
0

我正在使用Entity Framework(Code-First)創建一個數據庫,其中的一部分包含兩個具有多對多關係的實體。這裏是他們的代碼:實體框架多對多更新而不創建重複項?

public class Product 
{ 
    [Key] 
    public int ProductId { get; set; } 

    [MaxLength(50)] 
    public string CUSIP { get; set; } 

    [MaxLength(50)] 
    public string SEDOL { get; set; } 

    [MaxLength(50)] 
    public string BUID { get; set; } 

    [MaxLength(50)] 
    public string Key { get; set; } 

    [Required] 
    public bool Track { get; set; } 

    [InverseProperty("Products")] 
    [ForeignKey("ProductListId")] 
    public virtual List<ProductList> ProductLists { get; set; } 

    public override string ToString() 
    { 
     return String.Format("PRODUCT[ ProductId: {0}, CUSIP: {1}, SEDOL: {2}, BUID: {3}, Key: {4}, Track: {5}, ProductLists: {6} ]", 
          ProductId, 
          CUSIP, 
          SEDOL, 
          BUID, 
          Key, 
          Track, 
          (ProductLists != null ? ""+ProductLists.Count : "null")); 
    } 
} 

public class ProductList 
{ 
    [Key] 
    public int ProductListId { get; set; } 

    [Required] 
    [MaxLength(50)] 
    public string Name { get; set; } 

    [InverseProperty("ProductLists")] 
    [ForeignKey("ProductId")] 
    public virtual List<Product> Products { get; set; } 

    public override string ToString() 
    { 
     return String.Format("PRODUCT-LIST[ ProductListId: {0}, Name: {1}, Products: {2} ]", 
          ProductListId, 
          Name, 
          (Products != null ? "" + Products.Count : "null")); 
    } 
} 

在我的倉庫,我試圖寫一個產品的更新方法,從而改變跟蹤布爾或添加/從productList的去除,將保存到數據庫中。我使用AngularJS和asp.net-MVC爲我的項目的其他部分,所以這裏是在ProductsController類的更新方法:

public void Put(int id, [FromBody] Product product) 
    { 
     _repo.UpdateProduct(id, product); 
     _repo.Save(); 
    } 

因爲這是從AngularJS調用,產品對象是從JS初始化目的。

最後,這裏的updateProduct法庫:

public bool UpdateProduct(int id, Models.Product product) 
    { 
     if (product != null) System.Diagnostics.Debug.WriteLine("UpdateProduct() [" + id + "]\n" + product.ToString()); 

     if (id == 0) return AddProduct(product); 

     try 
     { 
      Product ctxProduct = GetProduct(id); 
      if (ctxProduct != null && product != null) 
      { 
       ctxProduct.CUSIP = product.CUSIP; 
       ctxProduct.SEDOL = product.SEDOL; 
       ctxProduct.BUID = product.BUID; 
       ctxProduct.Key = product.Key; 
       ctxProduct.Track = product.Track; 

       /*ctxProduct.ProductLists = new List<ProductList>(); 
       for (int i = 0; i < product.ProductLists.Count; i++) 
       { 
        ctxProduct.ProductLists.Add((product.ProductLists[i].ProductListId == 0) 
               ? product.ProductLists[i] 
               : GetProductListIncludingProducts(product.ProductLists[i].ProductListId)); 

       }*/ 
       return true; 
      } 
      return false; 
     } 
     catch (Exception e) 
     { 
      System.Diagnostics.Debug.WriteLine(e.Message + "\n ----- " + e.InnerException); 
      return false; 
     } 
    } 

現在,應該更新productList的關係的部分被註釋掉。雖然是這樣,我可以更新產品中的任何其他字段,並且它會按預期工作。

如果我取消註釋此部分,代碼將在數據庫中創建重複的productLists,以及這些列表中包含的所有產品的重複項。

最後,如果我取代GetProductListIncludingProducts(product.ProductLists[i].ProductListId)GetProductList(product.ProductLists[i].ProductListId),我從_repo.Save()出現以下錯誤:

System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_dbo.ProductListProducts'. Cannot insert duplicate key in object 'dbo.ProductListProducts' 

GetProductListIncludingProducts()只是增加了.INCLUDE( 「產品」)在其調用上下文。

我想獲得更新方法,只需重新調整多對多關係而不會崩潰或創建大量重複數據。

回答

0

它花了一段時間,但我終於明白了。原來問題出在我的WebAPI格式器上。我的代碼默認爲XMLMediaFormatter - 當我期待它使用我設置的用於處理參考跟蹤的JsonMediaFormatter時。如果它有助於任何人,這裏是我的最終UpdateProduct方法,與JsonMediaFormatter一起工作:

public bool UpdateProduct(int id, Product product) 
    { 
     if (product != null) System.Diagnostics.Debug.WriteLine("UpdateProduct() [" + id + "] " + product.ToString()); 

     if (id == 0) return AddProduct(product); 

     try 
     { 
      Product ctxProduct = GetProductIncludingProductLists(id); 

      if (ctxProduct != null && product != null) 
      { 
       ctxProduct.CUSIP = product.CUSIP; 
       ctxProduct.SEDOL = product.SEDOL; 
       ctxProduct.BUID = product.BUID; 
       ctxProduct.Key = product.Key; 
       ctxProduct.Track = product.Track; 

       ctxProduct.ProductLists = new List<ProductList>(); 
       foreach (ProductList pl in product.ProductLists) 
        ctxProduct.ProductLists.Add(pl.ProductListId == 0 
               ? pl 
               : GetProductList(pl.ProductListId)); 
       return true; 
      } 
      return false; 
     } 
     catch (Exception e) 
     { 
      System.Diagnostics.Debug.WriteLine("Update Product Error: " + e.Message + "\nInner: " + e.InnerException); 
      return false; 
     } 
    }