我很长时间读者 - 第一次发布海报 - 经过无数个小时的研究实体框架问题,我觉得我需要一些帮助。我是C#的新手,也是编程新手,所以请耐心等待。
我的数据模型中有一个相当简单的多对多关系,使用Web 2.0样式的“标签”。班次有标签,用户有标签。
我正在从缓存转移。当我尝试复制一个班次,复制缓存副本中的班次细节和标签时,我会做以下(简化)。
Data.Shift s = new Data.Shift();
/* copy over a bunch of stuff from the cached shift object. I'll spare the boring details */
foreach (var t in shift.Tags) { //shift object is a cached object
Data.Tag dt = new Data.Tag
{
TagID = t.TagID,
Name = t.Name,
OrgID = t.OrgID,
};
s.Tags.Add(dt);
}
即使我已经在新的Data.Tag对象中显式设置了TagID,但在SaveChanges()上会将新标记插入到DB中,而不是仅仅在DB中已存在的标记上创建关系。 TagID是PK标识列
当我尝试以下代码时:
foreach (var t in shift.Tags){
s.Tags.Add(t)
}
它显然失败了,因为转移是从与当前请求的上下文不同的对象上下文缓存的。
有什么想法?据我所知:
这似乎是我想要做的一件非常简单的事情......
修改 好的 - 我尝试用两种解决方案更新我的代码但是我遇到了两个问题。让我们试试第一个:
// ctx is grabbed up here from HttpContext.Current.Items
Data.Shift s = new Data.Shift();
/* copy over a bunch of stuff from the cached shift object. I'll spare the boring details */
foreach (var t in shift.Tags) { //shift object is a cached object
Data.Tag dt = new Data.Tag
{
TagID = t.TagID,
Name = t.Name,
OrgID = t.OrgID,
};
ObjectStateEntry entry;
ctx.ObjectStateManager.TryGetObjectStateEntry(t.EntityKey, out entry);
if (entry == null || entry.State == EntityState.Detached) {
ctx.Tags.Attach(t);
}
s.Tags.Add(dt);
}
这会引发以下错误:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
我猜我得到的原因是这个错误,是因为移位对象及其标签被拉出缓存(显然来自不同的上下文)。想法?
答案 0 :(得分:1)
将TAgId
设置为现有值无关紧要。 EF是愚蠢的 - 它不会为你做任何Upsert / Merge。它不检查是否存在相同的实体,并且如果在数据库中自动生成TagId
,它甚至会在您调用SaveChanges
后丢弃您的值。
你要做什么?您必须手动告知EF Tag
不是新实体。
尝试:
Data.Shift s = new Data.Shift();
context.Shifts.AddObject(s); // Add a new shift
foreach (var t in shift.Tags)
{ //shift object is a cached object
Data.Tag dt = new Data.Tag
{
TagID = t.TagID,
Name = t.Name,
OrgID = t.OrgID,
};
context.Tags.Attach(Tag); // Attach an existing tag
s.Tags.Add(dt);
}
context.SaveChanges();
或
Data.Shift s = new Data.Shift();
foreach (var t in shift.Tags)
{ //shift object is a cached object
Data.Tag dt = new Data.Tag
{
TagID = t.TagID,
Name = t.Name,
OrgID = t.OrgID,
};
s.Tags.Add(dt);
}
context.Shifts.AddObject(s);
// Now shift and all tags are added
// Change the state of each tag to unchanged
foreach (var tag in s.Tags)
{
context.ObjectStateManager.ChangeEntityState(tag, EntityState.Unchanged);
}
context.SaveChanges();