Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架:附加类型为'的实体;国家';失败,因为相同类型的另一个实体已具有相同的主键值_C#_Sql_.net_Sql Server_Entity Framework - Fatal编程技术网

C# 实体框架:附加类型为'的实体;国家';失败,因为相同类型的另一个实体已具有相同的主键值

C# 实体框架:附加类型为'的实体;国家';失败,因为相同类型的另一个实体已具有相同的主键值,c#,sql,.net,sql-server,entity-framework,C#,Sql,.net,Sql Server,Entity Framework,我试图简化一个更复杂的数据模型,但为了清晰起见,让我们假设我有两个DB表:tb\u Item和tb\u Country,在tb\u Item表关联tb\u Country.CountryId和tb\u Item.MarketId 在代码中,我有Item和Country类,其中Country是Item的一个成员,因为我需要访问业务逻辑中的一些Country属性(但不应该与此问题相关) 当我从DB中检索要在UI中显示的项目记录时,我会执行以下操作(同样,简化): 其中FindItems是: publ

我试图简化一个更复杂的数据模型,但为了清晰起见,让我们假设我有两个DB表:
tb\u Item
tb\u Country
,在
tb\u Item
表关联
tb\u Country.CountryId
tb\u Item.MarketId

在代码中,我有
Item
Country
类,其中
Country
Item
的一个成员,因为我需要访问业务逻辑中的一些
Country
属性(但不应该与此问题相关)

当我从DB中检索要在UI中显示的项目记录时,我会执行以下操作(同样,简化):

其中
FindItems
是:

public IList<Item> FindItems(DateTime asOfDate, int? countryId)
{
    using (var ctx = GetContext())
    {
        var rawItems = ctx.Items.Include(x => x.Country).AsQueryable();

        var items = rawItems.Where(d => d.AsOfDate == rawItems.Where(d2 =>
                                                                d2.Country.IsoCountryCode == d.Country.IsoCountryCode && 
                                                                d2.AsOfDate <= asOfDate).Max(to2 => to2.AsOfDate));

        if (countryId.HasValue)
            items = items.Where(d => d.Country.CountryId == countryId.Value);

        return items.ToList();
    }
}
public Item GetItemById(long id)
{
    using (var ctx = GetContext())
    {
        return ctx.Items.SingleOrDefault(c => c.ItemId == id);
    }
}
public void SaveItem(Context ctx, Item item)
{
    ctx.Items.Attach(item);
    ctx.Entry(item).State = EntityState.Modified;
    ctx.Items.AddOrUpdate(item);
    ctx.SaveChanges();
}
…和
SaveItem
是:

public IList<Item> FindItems(DateTime asOfDate, int? countryId)
{
    using (var ctx = GetContext())
    {
        var rawItems = ctx.Items.Include(x => x.Country).AsQueryable();

        var items = rawItems.Where(d => d.AsOfDate == rawItems.Where(d2 =>
                                                                d2.Country.IsoCountryCode == d.Country.IsoCountryCode && 
                                                                d2.AsOfDate <= asOfDate).Max(to2 => to2.AsOfDate));

        if (countryId.HasValue)
            items = items.Where(d => d.Country.CountryId == countryId.Value);

        return items.ToList();
    }
}
public Item GetItemById(long id)
{
    using (var ctx = GetContext())
    {
        return ctx.Items.SingleOrDefault(c => c.ItemId == id);
    }
}
public void SaveItem(Context ctx, Item item)
{
    ctx.Items.Attach(item);
    ctx.Entry(item).State = EntityState.Modified;
    ctx.Items.AddOrUpdate(item);
    ctx.SaveChanges();
}
在执行
ctx.SaveChanges()
时,我正在保存一个带有
CountryId
的项目记录,该记录已经存在于
Country
表中,我得到了可怕的EF错误:

System.ServiceModel.FaultException:“附加类型为“MyService.Data.Model.Country”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”

我的问题是,我不希望在重复国家的
tb_项目
表上出现唯一性约束问题(我希望项目与国家的关系是多:一)。在将记录保存到
tbu项目
表时,代码几乎就好像试图将重复的国家/地区记录保存到
tbu国家/地区


我肯定我在做一些愚蠢的事情,我就是搞不懂它是什么……我尝试了其他相关问题中的建议:尝试分离
Country
模型,在检索记录时使用
AsNoTracking()
,在检索项目记录时不使用
。包括(x=>x.Country)
,等等。,但这一切都不管用。

有多种方法可以解释为什么会发生这种情况,但有一件事我看得很清楚,那就是为什么在连接实体之后调用AddOrUpdate?这只会再次尝试附加它,并会导致异常。请参见删除.attach或.AddOrUpdate行不会有任何区别,相同的错误。如果删除.Attach和.State行,则可以看到SQL Server错误:
System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参见内部异常。-->System.Data.Entity.Core.UpdateException:更新条目时出错。有关详细信息,请参见内部异常。-->System.Data.SqlClient.SqlException:违反唯一密钥约束“UQ\U tb\U国家代码”。无法在对象“dbo.tb_Country”中插入重复键。
根据错误消息,保存时不应发生此情况,但尝试将
附加到上下文时应发生此情况。如果没有更多的代码,很难说为什么会发生这种情况,但要点应该是您已经在某个地方附加了(例如)Id为1的国家(可能是因为包含调用)。然后,您还有另一个Id为1的对象引用,并尝试附加该对象引用,从而导致错误。快速而肮脏的修复方法是将FK添加到模型中,并且只设置CountryId。否则,请检查您的代码/EF调用和DbContext实例使用情况。@Jejuni所说的“将FK添加到模型”是指使用
[ForeignKey(“MarketId”)]
属性装饰Item.Country属性吗?我之前尝试过,但没有运气。假设我有3个项目,其中2个项目具有相同的子国家(Id 1)。我不认为这是一个问题,因为许多物品可以有相同的国家/一个国家可以属于许多物品。我没想到会爆炸。如果我在原始SQL中简单插入一个项目,我可以使用相同的国家Id添加任意多的项目行。