Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
Entity framework EF6:如何使用Select包含子属性,以便创建单个实例。避免";“相同主键”;错误_Entity Framework - Fatal编程技术网

Entity framework EF6:如何使用Select包含子属性,以便创建单个实例。避免";“相同主键”;错误

Entity framework EF6:如何使用Select包含子属性,以便创建单个实例。避免";“相同主键”;错误,entity-framework,Entity Framework,我正在尝试获取(以断开连接的方式)一个实体及其所有相关实体,然后尝试更新该实体。但我得到了以下错误: 附加“Feature”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。 公共阶层人士 { 公共int PersonId{get;set;} 公共字符串Personname{get;set} 公共ICollection地址{get;set;} } 公共类地址 { public int AddressId{get;set;} 公共int PersonId{get;set;} 公共字符串L

我正在尝试获取(以断开连接的方式)一个实体及其所有相关实体,然后尝试更新该实体。但我得到了以下错误:

附加“Feature”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。 公共阶层人士 { 公共int PersonId{get;set;} 公共字符串Personname{get;set} 公共ICollection地址{get;set;} }

公共类地址
{
public int AddressId{get;set;}
公共int PersonId{get;set;}
公共字符串Line1{get;set;}
公共字符串City{get;set;}
公共字符串状态{get;set;}
公众人物{get;set;}
公共ICollection功能{get;set;}
}
//多对多:在数据库中表示为AddressFeature(例如空调、中央供暖;用户可以选择单个地址的多个功能)
公共类功能
{
public int FeatureId{get;set;}
公共字符串特性名称{get;set;}
公共ICollection地址{get;set;}//多对多地址
}
公众人物候选人(内部id)
{
使用(MyDbContext=new MyDbContext())
{
var person=dbContext.People.AsNoTracking(),其中(x=>x.PersonId==id);
person=person.Include(prop=>prop.Addresses.Select(x=>x.Country)).Include(prop=>prop.Addresses.Select(x=>x.Features));
返回person.FirstOrDefault();
}
}
public void UpdateCandidate(Person newPerson)
{
Person existingPerson=GetPerson(Person.Id);//使用ASNOTRACKING从数据库加载现有候选人
dbContext.People.Attach(existingPerson);//此行给出错误信息
.....
.....
.....
}
错误: 其他信息:附加“Feature”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值

看起来(我可能错了)GetCandidate正在分配Person中的每个功能。处理一个新实例。那么,我如何修改GetCandidate以确保相同的实例(对于相同的值)被分配给Person.Addresses-->功能呢

请建议

看起来(我可能错了)GetCandidate正在分配Person中的每个功能。处理一个新实例。那么,我如何修改GetCandidate以确保相同的实例(对于相同的值)被分配给Person.Addresses-->功能呢

由于您使用的是短期的
DbContext
来检索数据,因此只需删除
AsNoTracking()
,从而允许EF使用上下文缓存并合并
功能
实体。EF跟踪有不同的用途。一个是允许使用您在本例中感兴趣的相同PK合并实体实例,第二个是在您修改实体并调用
SaveChanges()
时检测修改,显然您在使用上下文检索数据时并不感兴趣。禁用查询跟踪时,EF无法使用缓存,因此会生成单独的对象实例

您真正不希望的是让EF创建代理,这些代理包含对用于获取它们的上下文的引用,并且在尝试附加到另一个上下文时会导致问题。我在您的模型中没有看到
virtual
导航属性,因此EF很可能不会创建代理,但为了绝对确定,我将关闭
ProxyCreationEnabled

public Person GetCandidate(int id)
{
    using (MyDbContext dbContext = new MyDbContext())
    {
         dbContext.Configuration.ProxyCreationEnabled = false;
         var person = dbContext.People.Where(x => x.PersonId == id);
         person = person.Include(prop => prop.Addresses.Select(x => x.Country)).Include(prop => prop.Addresses.Select(x => x.Features));
         return person.FirstOrDefault();
     }
}

这是
AsNoTracking
的副作用。最好设置
dbContext.Configuration.ProxyCreationEnabled=false
检索数据并删除
AsNoTracking
。ProxyCreationEnabled已为false,但我确实希望使用AsNoTracking,因为我希望EF不跟踪实体。是否可能需要实施其中一种设置?是否可以使用AsNoTracking并避免我得到的错误?跟踪意味着允许使用db上下文缓存。如果不允许使用缓存,EF将生成单独的实例。就这么简单。我看不出在像
GetCandidate
方法那样的短期数据库上下文中使用上下文跟踪服务有什么问题。只要EF不创建代理,返回的对象就不会引用用于获取它们的db上下文。酷。谢谢你,伊万。这帮了大忙。我怎么能接受你的答案呢?伊万,你能不能把它贴出来,这样我就可以接受你的答案了。
public Person GetCandidate(int id)
{
    using (MyDbContext dbContext = new MyDbContext())
    {
         dbContext.Configuration.ProxyCreationEnabled = false;
         var person = dbContext.People.Where(x => x.PersonId == id);
         person = person.Include(prop => prop.Addresses.Select(x => x.Country)).Include(prop => prop.Addresses.Select(x => x.Features));
         return person.FirstOrDefault();
     }
}