我有一个名为
Personel
的表,每个 Personel
包含一个 List<Eblagh>
。其中有一个名为 Vahed
的属性。
我想找到人员(eblaghs)中可用的所有
Vahed
,并将它们插入另一个名为School
的表中,在该表中,我们必须有一列来保存所有相关的Personel
。
这些是我的课程:
public class Personel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
...
public int AreaId { get; set; }
public Area Area { get; set; }
public List<PersonelSchool> PersonelSchools { get; set; } = new();
public List<Eblagh> Eblaghs { get; set; } = new();
}
public class Eblagh
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Vahed { get; set; }
...
public int PersonelId { get; set; }
public Personel Personel { get; set; }
}
public class School
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public List<PersonelSchool> PersonelSchools { get; set; } = new();
}
public class PersonelSchool
{
public int PersonelId { get; set; }
public Personel Personel { get; set; }
public int SchoolId { get; set; }
public School School { get; set; }
}
我使用了以下代码:
var personelsWithEblagh =
await db.Personels
.Where(x => x.AreaId == Area.Id)
.Include(p => p.Eblaghs)
.ToListAsync();
foreach (var personel in personelsWithEblagh)
{
foreach (var eblagh in personel.Eblaghs)
{
var schoolName = eblagh.Vahed;
var existingSchool = await db.Schools.FirstOrDefaultAsync(s => s.Name == schoolName);
if (existingSchool == null)
{
var newSchool = new School { Name = schoolName };
await db.Schools.AddAsync(newSchool);
await db.SaveChangesAsync();
existingSchool = newSchool;
}
personel.PersonelSchools.Add(new PersonelSchool
{
PersonelId = personel.Id,
SchoolId = existingSchool.Id
});
}
}
await db.SaveChangesAsync();
这是我的
DbContext
:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PersonelSchool>()
.HasKey(ps => new { ps.PersonelId, ps.SchoolId });
modelBuilder.Entity<PersonelSchool>()
.HasOne(ps => ps.Personel)
.WithMany(p => p.PersonelSchools)
.HasForeignKey(ps => ps.PersonelId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<PersonelSchool>()
.HasOne(ps => ps.School)
.WithMany(s => s.PersonelSchools)
.HasForeignKey(ps => ps.SchoolId)
.OnDelete(DeleteBehavior.Cascade);
}
问题是操作抛出错误
System.InvalidOperationException:实体类型的实例 无法跟踪“PersonelSchool”,因为另一个实例具有 {'PersonelId', 'SchoolId'} 的相同键值已被使用 被跟踪。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用 'DbContextOptionsBuilder.EnableSensitiveDataLogging' 查看 关键值冲突。
在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap
1.Add(TKey 键,InternalEntityEntry 条目,布尔值 updateDuplicate)1.ThrowIdentityConflict(InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap
在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap1.Add(InternalEntityEntry 条目)1.Add(TKey key, InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NullableKeyIdentityMap
如果我添加
.AsNoTracking()
,学校名称将被添加到表中,但是,我再次收到错误并且PersonelSchool
表为空
您可以在插入关联项目之前检查预先存在的项目,如下面的代码所示 - 即在 PersonnelsWithEBlagh 中包含 PersonnelSchools,并在添加之前检查其内容。您可能最好确定为什么它会插入您不希望插入的项目。
var personelsWithEblagh =
await db.Personels
.Where(x => x.AreaId == Area.Id)
.Include(p => p.Eblaghs)
.Include(p => p.PersonelSchools // Include the existing personnelschools
.ToListAsync();
foreach (var personel in personelsWithEblagh)
{
foreach (var eblagh in personel.Eblaghs)
{
var schoolName = eblagh.Vahed;
var existingSchool = await db.Schools.FirstOrDefaultAsync(s => s.Name == schoolName);
if (existingSchool == null)
{
var newSchool = new School { Name = schoolName };
await db.Schools.AddAsync(newSchool);
await db.SaveChangesAsync();
existingSchool = newSchool;
}
if(!personel.PersonelSchools.Any(x=>x.SchoolId == existingSchool.Id)) // Check for existing item in the association table
{
personel.PersonelSchools.Add(new PersonelSchool
{
PersonelId = personel.Id,
SchoolId = existingSchool.Id
});
}
}
}
await db.SaveChangesAsync();