EF6:如何在 Select 中包含子属性,以便创建单个实例。避免"same primary key"错误



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

附加类型为"功能"的实体失败,因为相同类型的另一个实体已具有相同的主键值。 公共类人 { public int PersonId { get; set; } 公共字符串 人名 { get; set } public ICollection Addresses{ get; set; } }

public class Address
{
public int AddressId { get; set; }
public int PersonId { get; set; }
public string Line1 { get; set; }
public string City { get; set; }
public string State { get; set; }
public Person Person { get; set; }
public ICollection<Feature> Features { get; set; } 
}
// Many to Many: Represented in database as AddressFeature (e.g Air Conditioning, Central Heating; User could select multiple features of a single address)
public class Feature
{
public int FeatureId { get; set; }
public string Featurename { get; set; }
public ICollection<Address> Addresses { get; set; } // Many-To-Many with Addresses
}
public Person GetCandidate(int id)
{
using (MyDbContext dbContext = new MyDbContext())
{
var person = dbContext.People.AsNoTracking().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();
}
}
public void UpdateCandidate(Person newPerson)
{
Person existingPerson = GetPerson(person.Id); // Loading the existing candidate from database with ASNOTRACKING
dbContext.People.Attach(existingPerson); // This line is giving error
.....
.....
.....
}

错误: 其他信息:附加类型为"功能"的实体失败,因为相同类型的另一个实体已具有相同的主键值。

看起来(我可能是错的)GetCandidate 正在分配 Person.Address 中的每个功能。那么,我该如何修改 GetCandidate 以确保相同的实例(对于相同的值)正在协助 Person.Addresses --> 功能。

恳请建议。

似乎

(我可能是错的)GetCandidate 正在分配 Person.Address 中的每个功能。那么,我该如何修改 GetCandidate 以确保相同的实例(对于相同的值)正在协助 Person.Addresses --> 功能。

由于你使用的是短期DbContext来检索数据,因此只需删除AsNoTracking(),从而允许 EF 使用上下文缓存并合并Feature实体。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();
}
}

最新更新