2009-10-23 124 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