当我尝试删除实体时,我收到以下错误:
“ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法跟踪具有相同对象的多个对象 键“。
我已阅读此处与此错误相关的其他帖子,并尝试分离过滤器,没有运气。也许我错过了一些简单的东西,或者应该使用不同的方法来删除这些过滤器(我已经尝试过删除方法)?任何帮助将不胜感激。
以下是代码:我使用的是ASP.NET 4.5和EF 5.这个简单的存储库类在存储库构造函数中初始化了一个私有dbContext,并在析构函数中被销毁。
namespace AuditLog.Repositories
{
public class FilterSetRepository : IFilterSetRepository
{
private readonly AuditLogEntities _ctx;
/// <summary>
/// Default constructor
/// </summary>
public FilterSetRepository()
{
_ctx = new AuditLogEntities();
}
/// <summary>
/// Destructor
/// </summary>
~FilterSetRepository()
{
_ctx.Dispose();
}
在foreach循环中有_ctx.Entry(filter).State = EntityState.Deleted;
的行(下面)抛出错误。名为FilterSet的实体有一个Filter实体列表,在我删除FilterSet之前必须从它们的表中删除它们。如有必要,我可以提供显示它们的类代码。
在违规行的上方是我尝试分离方法的地方,但是它说它无法分离,因为还没有附加密钥。
/// <summary>
/// Delete a particular filter set and its filters.
/// </summary>
/// <param name="filterSet">The filter set to be deleted.</param>
public void DeleteFilterSet(FilterSet filterSet)
{
// First delete the child elements
var filterRepository = new FilterRepository();
foreach (var filter in filterRepository.GetFiltersBySets(filterSet))
{
_ctx.Entry(filter).State = EntityState.Deleted;
_ctx.SaveChanges();
}
// ...then delete the filter set
_ctx.Entry(filterSet).State = EntityState.Deleted;
_ctx.SaveChanges();
}
提前感谢您的帮助!
答案 0 :(得分:2)
再次阅读此post后,我能够修改我的DeleteFilterSet代码,以查找和处理对象状态管理器已经跟踪密钥的对象。以下是有效的代码:
/// <summary>
/// Delete a particular filter set and its filters.
/// </summary>
/// <param name="filterSet">The filter set to be deleted.</param>
public void DeleteFilterSet(FilterSet filterSet)
{
// First delete the child elements
var filterRepository = new FilterRepository();
foreach (var filter in filterRepository.GetFiltersBySets(filterSet))
{
var entry = _ctx.Entry(filter);
if (entry.State==EntityState.Detached)
{
var set = _ctx.Set<Filter>();
Filter attachedEntity = set.Local.SingleOrDefault(e => e.FilterId == filter.FilterId);
if (attachedEntity!=null)
{
var attachedEntry = _ctx.Entry(attachedEntity);
attachedEntry.State=EntityState.Deleted;
}
else
{
entry.State = EntityState.Deleted;
}
}
_ctx.SaveChanges();
}
// ...then delete the filter set
_ctx.FilterSets.Remove(filterSet);
_ctx.SaveChanges();
}
我希望这个解决方案可以帮助其他人。
答案 1 :(得分:1)
_ctx.Entry(filter).State = EntityState.Deleted;
会对状态进行大量额外检查。
如果您已经拥有过滤器对象,则可能需要使用:
_ctx.Attach(filter);
_ctx.Filter.Remove(filter);
_ctx.SaveChanges();
答案 2 :(得分:1)
我曾经遇到过这个异常并用它来修复它,当你想要一个对象添加到上下文(附加)并且dbcontext中已经存在另一个具有相同主键值的对象时,它就会发生。 我建议你在你的sql存储库中添加一个Attach方法,如下所示:
public void Attach(T itemToBeAttached)
{
T old = _objectSet.Local.FirstOrDefault(i => i.Id == itemToBeAttached.Id);
if (old != null)
{
_context.Entry<T>(old).State = EntityState.Detached;
}
_objectSet.Attach(itemToBeAttached);
}
这里的关键是objectSet的加载属性。
当你想要删除一个实体并且实体dosnt存在于对象上下文中时,它首先检查是否附加了对象的状态,如果它没有附加,那么ef将附加到db那些如果另一个对象已经存在则抛出exceptin的地方具有相同密钥的上下文。