由于出现常见的实体框架错误而感到困惑
"附加类型为' MyType'的实体失败是因为 另一个相同类型的实体已经拥有相同的主键 值。
我对这个错误的理解是,这意味着该对象类型的图形中有另一个对象,它具有重复的主键,防止附加第二个副本。
但这种理解肯定是错误的,因为错误发生在这里:
public void Update(MyType updateItem)
{
if (updateItem != null)
{
// debug code, which tells me there is only one match
var foo = Entities.MyTypes.Where(x => x.MyTypeId == updateItem.MyTypeId);
if (Entities.MyTypes.Any(itm => itm.MyTypeId == updateItem.MyTypeId))
{
// error here
Entities.Entry(updateItem).State = System.Data.Entity.EntityState.Modified;
}
else
{
Entities.MyTypes.Add(updateItem);
}
}
}
为了不尝试添加或重新附加新对象,它只是说现有对象被标记为已修改,对吧?
有人可以在这里向我解释这个过程,所以我可以尝试理解并解决问题吗?
编辑:这是它试图运行的SQL
exec sp_executesql N'SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[MyType] AS [Extent1]
WHERE [Extent1].[MyTypeId] = @p__linq__0
)) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]',N'@p__linq__0 int',@p__linq__0=4749
返回C1值1.跟踪中的下一个条目是记录错误的记录器。
答案 0 :(得分:0)
经过多次浪费时间之后,我发现这是有效的,根据这个答案:https://stackoverflow.com/a/31771363/271907
// needs this namespace
using System.Data.Entity.Migrations;
public void Update(MyType updateItem)
{
if (updateItem != null)
{
if (Entities.MyTypes.Any(itm => itm.MyTypeId == updateItem.MyTypeId))
{
try
{
Entities.Entry(updateItem).State = System.Data.Entity.EntityState.Modified;
}
catch
{
Entities.Set<MyType>().AddOrUpdate(updateItem);
}
}
else
{
Entities.MyTypes.Add(updateItem);
}
}
}
但是,我必须承认我不明白为什么它完全有效,我仍然对原始错误的原因感到困惑。
我可能不需要那里的try / catch块 - 也许我应该换掉State = Modified
来调用AddOrUpdate()
。但是因为旧的代码功能正常,而且我不确定为什么会这样,所以我觉得把它放在一边是最明智的。