簡體   English   中英

使用相關實體更新實體框架

[英]Entity Framework Updating with Related Entity

我正在使用EF嘗試使用ASP.NET更新實體。 我正在創建一個實體,設置它的屬性然后將其傳遞回具有ID的單獨圖層上的EF,以便可以應用更改。 我這樣做是因為我只存儲實體的ID,當它綁定到UI控件時。

一切都適用於標准屬性,但我無法更新產品(相關實體)的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時遇到了一些問題。

失敗的原因有兩個。

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

所以我會做這樣的事情(注意這段代碼大量使用稱為存根實體的技巧,以避免與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();
 }
}

如果沒有錯別字等,這將完成這項工作。

這是帶有實體框架的強類型ASP.NET MVC這個問題的公認答案

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才能更改關系的狀態。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM