使用相关实体更新实体框架
-
06-07-2019 - |
题
我正在使用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时遇到了一些问题。
解决方案
这是强类型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才能改变关系的状态。
其他提示
失败的原因有两个。
- 要更新参考(即Product.Category),您还必须在上下文中包含原始参考值。
- 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();
}
}
如果没有拼写错误等,这将完成工作。
不隶属于 StackOverflow