我有一个实体假设[MainEntity]。这个主要实体有一些子实体,如下所示:
MainEntity:
-> ChildEntity1
-> ChildEntity2
-> ChildEntity3
-> ChildEntity4
-> ChildEntity5
所有子实体与主要实体都有一对多的关系。
在主要实体的UI用户更新数据以及前3个子实体中。在UI ChildEntity1中,ChildEntity2,ChildEntity3由GridView,ListBox和CheckListBox表示。用户可以通过这些控件添加/更新子记录。插入/更新数据的示例代码如下所示:
BL class:
========
public class EntityManager
{
public EntityManager ()
{
MainEntityData = new MainEntity();
}
public MainEntity MainEntityData= { get; set; }
public void InsertUpdate()
{
DAL.InsertMainEntityData(MainEntityData);
}
}
UI Codes:
=========
EntityManager objEntityManager = new EntityManager();
if (lnkInsertUpdate.CommandArgument == "Update")
objEntityManager.MainEntity.ID =
int.Parse(Request.QueryString["ID"].ToString());
objEntityManager.MainEntity.Name = txtName.Text;
objEntityManager.MainEntity.Description = txtDescription.Text;
-----------------------------------------
-----------------------------------
ChildEntity1 objChildEntity1 = null;
foreach (ListItem item in lstSelectedProduct.Items)
{
objChildEntity1 = new ChildEntity();
objChildEntity1.ClientProductID = int.Parse(item.Value);
objChildEntity1.IsActive = true;
objChildEntity1.CreatedBy = "Admin";
objChildEntity1.CreatedDate = DateTime.Now;
objEntityManager.MainEntity.ChildEntitys1.Add(objChildEntity1);
}
-----------------------------------
codes for childentity2,childentity3
--------------------------------
objEntityManager.InsertUpdate()
DALCodes:
=========
public static void InsertMainEntityData(MainEntity objMainEntity)
{
using (TransactionScope ts = new TransactionScope())
{
try
{
using (DBEntities context = DatabaseFactory.GetContext())
{
if (objMainEntity.ID > 0)
{
MainEntity mainEntityToUpdate =
context.MainEntitys.Include("ChildEntity1").Include("ChildEntity2").Include("ChildEntity3").First(o => o.ID == objMainEntity.ID);
mainEntityToUpdate = objMainEntity;
context.MainEntitys.Attach(mainEntityToUpdate);
context.ObjectStateManager.ChangeObjectState(mainEntityToUpdate,
EntityState.Modified);
}
else
{
context.AddToMainEntitys(objMainEntity);
context.SaveChanges();
ts.Complete();
}
catch (Exception ex)
{
ts.Dispose();
}
finally
{
}
}
插入新的reord工作正常但在更新时给出以下错误:
ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。
请指导如何解决此问题?
谢谢,
保
答案 0 :(得分:1)
您有此错误,因为您在此行中使用分离的mainEntityToUpdate
覆盖已加载的objMainEntity
:
mainEntityToUpdate = objMainEntity;
然后你附上这个对象:
context.MainEntitys.Attach(mainEntityToUpdate);
因为mainEntityToUpdate
仍附加到上下文(加载后),所以有两个对象附加到上下文中的相同键被禁止并导致异常。
您可以使用以下代码更新实体的标量属性:
MainEntity mainEntityToUpdate = context.MainEntitys
.First(o => o.ID == objMainEntity.ID);
context.MainEntitys.ApplyCurrentValues(objMainEntity);
但它只更新标量属性,而不更新子集合 - 因为将状态设置为Modified
也不会导致子集合的更新。
更新主实体(包括所有子集合)实际上并不那么容易。您必须加载原始实体,包括数据库中的所有子集合(您开始加载Include("ChildX")
的主实体是正确的),然后将其与分离的objMainEntity
及其更新的集合进行比较。 “比较”表示:您必须检测用户已添加哪个集合项目,哪些集合项目已被删除,哪些集合项目仍然存在(但可能已更改属性值),然后相应地在原始集合中添加或删除项目。更改检测将遵循这些更改,并在您调用SaveChanges
时将相应的SQL语句写入数据库。
草图如何执行此操作(对于DbContext
/ EF> = 4.1),请执行以下操作:https://stackoverflow.com/a/5540956/270591