2009-10-23 121 views
3

我正在使用EF嘗試使用ASP.NET更新實體。我正在創建一個實體,設置它的屬性,然後將它傳遞迴帶有ID的單獨圖層上的EF,以便可以應用更改。我這樣做是因爲我只在被綁定到UI控件時存儲實體的ID。使用相關實體更新實體框架

一切適用於標準屬性,但我無法更新產品(相關實體)的Category.ID。我已經嘗試了EntityKey,EntityReference和其他一些,但是類別ID沒有保存。這是我的:

Product product = new Product(); 
product.CategoryReference.EntityKey = new EntityKey("ShopEntities.Categories", "CategoryID", categoryId); 
product.Name = txtName.Text.Trim(); 
... other properties 
StockControlDAL.EditProduct(productId, product); 

public static void EditProduct(int productId, Product product) { 
using(var context = new ShopEntities()) { 
    var key = new EntityKey("ShopEntities.Products", "ProductID", productId); 
    context.Attach(new Product() { ProductID = productId, EntityKey = key }); 
    context.AcceptAllChanges(); 
    product.EntityKey = key; 
    product.ProductID = productId; 
    context.ApplyPropertyChanges("ShopEntities.Products", product); 
    context.SaveChanges(); 
} 
} 

我真的想使用EF,但我似乎有一些使用它與ASP.NET的問題。

回答

0

這是接受這個問題的答案Strongly-Typed ASP.NET MVC with Entity Framework

context.AttachTo(product.GetType().Name, product); 
ObjectStateManager stateMgr = context.ObjectStateManager; 
ObjectStateEntry stateEntry = stateMgr.GetObjectStateEntry(model); 
stateEntry.SetModified(); 
context.SaveChanges(); 

你試過了嗎?

[更新,在上面的代碼不起作用]

這是小的擴展屬性我用這樣一個代碼塊是比較容易理解:

public partial class Product 
{ 
    public int? CategoryID 
    { 
     set 
     { 
      CategoryReference.EntityKey = new EntityKey("ShopEntities.Categories", "CategoryID", value); 
     } 
     get 
     { 
      if (CategoryReference.EntityKey == null) 
       return null; 

      if (CategoryReference.EntityKey.EntityKeyValues.Count() > 0) 
       return (int)CategoryReference.EntityKey.EntityKeyValues[0].Value; 
      else 
       return null; 
     } 
    } 
} 

和工作對我來說(這時間肯定):

System.Data.EntityKey key = new System.Data.EntityKey("ShopEntities.Products", "ProductID", productId); 
     object originalItem; 

     product.EntityKey = key; 
     if (context.TryGetObjectByKey(key, out originalItem)) 
     { 
      if (originalItem is EntityObject && 
       ((EntityObject)originalItem).EntityState != System.Data.EntityState.Added) 
      { 
       Product origProduct = originalItem as Product; 
       origProduct.CategoryID == product.CategoryID;//set foreign key again to change the relationship status   
       context.ApplyPropertyChanges(
        key.EntitySetName, product); 

      } 
     }context.SaveChanges(); 

肯定它看起來很不好意思。我認爲,原因是因爲EF關係具有作爲實體的狀態(修改,添加,刪除),並且基於該狀態,EF會更改外鍵的值或刪除行,如果多對多關係在情況下。出於某種原因(不知道爲什麼),關係狀態不會與財產狀態相同。這就是爲什麼我必須在originalItem上設置CategoryReference.EntityKey才能更改關係的狀態。

+0

沒有被保存。 – Echilon 2009-10-23 12:17:44

+0

對不起,Echilion,看看更新的答案。這次它肯定有效。 – 2009-10-23 15:06:06

+0

最後!謝謝Misha,我即將拋棄EF,但你已經恢復了我的信心! – Echilon 2009-10-23 15:56:30

6

這失敗的原因是兩倍。

  1. 爲了更新引用(即Product.Category),您還必須在上下文中具有原始引用值。
  2. ApplyPropertyChanges(...)只適用於實體的常規/標量屬性,基準保持不變

所以我會做這樣的事情(注意此代碼大量使用了一種叫做stub entities絕招爲了避免擺弄周圍EntityKeys)

Product product = new Product(); 
// Use a stub because it is much easier. 
product.Category = new Category {CategoryID = selectedCategoryID}; 
product.Name = txtName.Text.Trim(); 
... other properties 

StockControlDAL.EditProduct(productId, originalCategoryID); 


public static void EditProduct(Product product, int originalCategoryID) { 
using(var context = new ShopEntities()) 
{ 
    // Attach a stub entity (and stub related entity) 
    var databaseProduct = new Product { 
      ProductID = product.ProductID, 
      Category = new Category {CategoryID = originalCategoryID} 
     }; 
    context.AttachTo("Products", databaseProduct); 

    // Okay everything is now in the original state 
    // NOTE: No need to call AcceptAllChanges() etc, because 
    // Attach puts things into ObjectContext in the unchanged state 

    // Copy the scalar properties across from updated product 
    // into databaseProduct in the ObjectContext 
    context.ApplyPropertyChanges("ShopEntities.Products", product); 

    // Need to attach the updated Category and modify the 
    // databaseProduct.Category but only if the Category has changed. 
    // Again using a stub. 
    if (databaseProduct.Category.CategoryID != product.Category.CategoryID) 
    { 
     var newlySelectedCategory = 
       new Category { 
        CategoryID = product.Category.CategoryID 
       }; 

     context.AttachTo("Categories", newlySelectedCategory) 

     databaseProduct.Category = newlySelectedCategory; 

    } 

    context.SaveChanges(); 
} 
} 

這將做的工作,假設沒有錯別字等,當我嘗試這種方法

+0

謝謝,這兩個解決方案的工作,但我只能標記一個答案。 作爲應用程序的一部分,但我需要更新一個分離的實體列表(而不是一個類別,一些實體將有一個子項目列表(例如訂單))。我看不出如何使這種解決方案適應這種情況。可能嗎? – Echilon 2009-10-23 19:13:58