如何将更改保存到相关表中的MVC 5和6 EF - 实体框架主详细 [英] How to save changes to related table in MVC 5 and EF 6 - Entity Framework Master-Detail
问题描述
我有两个表,促进和PromotionLine,定义为PromotionLine.PromoID = Promotion.ID
I have two tables, Promotion and PromotionLine, with a foreign key defined as PromotionLine.PromoID = Promotion.ID
PromotionLines与在促进类以下的推广模式有关
PromotionLines are associated with the Promotion model with the following in the Promotion class:
public IList<PromotionLine> PromotionLineItems { get; set; }
我选择不使用虚拟的,因为我不想,如果我们只使用一个摘要视图,显示高层次的促销信息(如促销的列表)加载的宣传片线。
I chose not to use virtual because I don't want the promo lines loaded if we're just using a summary view to show high level Promotion info (such as a list of Promotions).
当需要推广的细节,我得到推广行:
When promotion details are needed, I get the promotion lines:
public static Promotion GetInstance(int? promotionId)
{
if (promotionId == null) return null;
using (APP01Entities entities = new APP01Entities())
{
return entities.Promotions
.Include(s => s.PromotionState)
.Include(h => h.PromotionHeaderType)
.Include(l => l.PromotionLineItems)
.Include(c => c.PromotionComments)
.FirstOrDefault(p => p.ID == promotionId);
}
}
这工作,我可以在我看来访问推广线。
This works, and I can access the promotion lines in my view.
然而,当我去更新的变化,我遇到的错误:
However, when I go to update changes, I encounter the error:
参照完整性约束冲突发生了:该物业
Promotion.ID'的值(S)的关系的一端不匹配
属性值(S)对对方的PromotionLine.PromotionID
结束。
"A referential integrity constraint violation occurred: The property value(s) of 'Promotion.ID' on one end of a relationship do not match the property value(s) of 'PromotionLine.PromotionID' on the other end."
我明白为什么这个错误发生。我不知道怎么去解决它。
我使用的是默认的更新方法(由EF脚手架创建):
I understand WHY this error is occurring. I don't know how to get around it. I'm using the default update method (created by EF scaffolding):
public bool Update()
{
try
{
using (APP01Entities entities = new APP01Entities())
{
entities.Promotions.Attach(this);
var entity = entities.ChangeTracker.Entries<Promotion>().FirstOrDefault(e => e.Entity == this);
if (entity == null)
{
return false;
}
entity.State = EntityState.Modified;
entities.SaveChanges();
}
return true;
}
catch (System.Data.Entity.Validation.DbEntityValidationException e)
{
throw e.Improve();
}
}
的问题是:
entities.Promotions.Attach(this);
这有推广线。 entities.Promotions没有。
"this" has the promotion lines. entities.Promotions does not.
下面是如何我调用更新方法:
Here is how I'm calling the update method:
[HttpPost]
public ActionResult Edit(Promotion promotion)
{
if (ModelState.IsValid)
{
promotion.Update();
}
return View(promotion);
}
问题
- 如何升迁线路加入到entities.Promotions?
- 或者,我应该有不同的接近此更新?
推荐答案
这并不是一个简单的任务。您需要更新您的对象图。换句话说,你需要一个主详细更新。
This is not a trivial task. You need to update your object graph. In other word you need a Master-Detail update.
要保持答案简单,我想我有一个订单
实体具有订单明细
属性,它是一个列表与LT;&的OrderDetail GT;
编辑的时候。你要注意:
To keep the answer simple I suppose I have an Order
entity that have OrderDetails
property that is a List<OrderDetail>
.You should pay attention when editing:
- 有一些
的OrderDetail
已添加到订单明细
和他们的主要标志是有编号
属性等于0。 - 某些
的OrderDetail
已被删除并不再存在订单明细
- 某些
的OrderDetail
已被更改。
- There are some
OrderDetail
that have been added toOrderDetails
and the main sign of them is havingId
property equal to 0. - Some
OrderDetail
have been removed and no longer exist inOrderDetails
- Some
OrderDetail
have been changed.
在更新订单
则应该更新订单
本身也适用上述变化。
When updating the Order
you should update the Order
itself and also apply above changes.
步骤
下面是步骤:
- 从数据库中获取原始顺序。
- 更新使用编辑秩序原订单的价值。
- 找到添加的产品清单(添加的项目的ID为0)。
- 找到删除的项目清单(原订单的订单详细信息列表,其中的原始顺序细节id是不是编辑订单订单详细信息IDS之间)。
- 找到编辑资料(原始顺序,其中的原始顺序细节的id是编辑订单的订单详细信息ID之间的订单详情列表)的列表。
- 使用一个遍历删除的项目清单,并设置它们的状态中删除。
- 使用循环编辑过的物品清单,并已在上下文中加载的原订单的详细信息更新的价值。
- 使用一个循环结束添加的项目清单,并设置他们的状态加入。
- 设置原始订单的状态修改。
- 保存环境的变化。
code
下面是code:
public void Update(Order editedOrder)
{
var context = new YourDbContext();
//Get original order from database.
var originalOrder = context.Orders.Including("OrderDetails").Where(x => x.OrderId == editedOrder.OrderId).FirstOrDefault();
//Update the value of original order using edited order.
context.Entry(originalOrder).CurrentValues.SetValues(editedOrder);
//Find list of added items (Id of added items is 0).
var addedList = editedOrder
.OrderDetails
.Where(y => y.OrderDetailId == 0)
.ToList();
//Find list of removed items.
var deletedList = originalOrder
.OrderDetails
.Where
(
x =>
(
!editedOrder.OrderDetails
.Select(y => y.OrderDetailId)
.Contains(x.OrderDetailId)
)
)
.ToList();
//Find list of edited items.
var editedList = editedOrder.OrderDetails
.Where
(
y => originalOrder
.OrderDetails
.Select(z => z.OrderDetailId)
.Contains(y.OrderDetailId)
)
.ToList();
//Use a loop over deleted items list and set state of them to removed.
deletedList.ForEach(deletedDetail =>
{
originalOrder.OrderDetails.Remove(deletedDetail);
context.Entry(editedOrder).State = EntityState.Deleted;
});
//Use a loop over edited items list and update value of original order details that have been loaded in context.
editedList.ForEach(editedDetail =>
{
var originalOrderDetail = originalOrder.OrderDetails.Where(x => x.OrderDetailId == editedDetail.OrderDetailId).FirstOrDefault();
context.Entry(originalOrderDetail).CurrentValues.SetValues(editedDetail);
});
//Use a loop over added items list and set state of them to added.
addedList.ForEach(addedDetail =>
{
originalOrder.OrderDetails.Add(addedDetail);
});
//Set the state of original order to modified.
context.Entry(oroginalOrder).State = System.Data.Entity.EntityState.Modified;
//Save context changes.
context.SaveChanges();
}
这篇关于如何将更改保存到相关表中的MVC 5和6 EF - 实体框架主详细的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!