EF Core 一对一关系交换引用问题
Posted
技术标签:
【中文标题】EF Core 一对一关系交换引用问题【英文标题】:EF Core one-to-one relationship swapping references issue 【发布时间】:2020-05-24 14:08:57 【问题描述】:我有两个实体
public class Student
public int Id get; set;
public string Name get; set;
public StudentAddress Address get; set;
和
public class StudentAddress
public int StudentAddressId get; set;
public string Address get; set;
public string City get; set;
public string State get; set;
public string Country get; set;
public int StudentId get; set;
public Student Student get; set;
基本上是一对一的关系
我有这样的代码
var students = await context.Students.Include(s => s.Address).ToListAsync();
var student1 = students[0];
var student2 = students[1];
var st1Addr = student1.Address;
var st2Addr = student2.Address;
student1.Address = st2Addr;
student2.Address = st1Addr;
await context.SaveChangesAsync();
当 EF 保存更改时,其中一条学生地址记录会从 DB 中删除。
我需要更改对学生地址的引用。如何使用 EF 核心实现这一目标?
【问题讨论】:
能否分享两条记录的底层数据? 【参考方案1】:因为是1对1的关系,只要你设置好
student1.Address = st2Addr;
必须删除学生 1 的旧地址,因为它会违反对 SudentAddress.StudentId 的唯一约束。这不仅仅是变更跟踪器的限制。 SaveChanges 将无法运行
UPDATE StudentAddress set StudentId = @StudentId where StudentAddressID = @Id
没有先删除另一行,因为它会违反唯一约束。并且通常对每个 DML 语句强制执行约束,而不是推迟到事务提交之前。您可以在 SQL 中使用单个更新语句来执行此操作,例如
update SudentAddress set StudentID = case when studentId = 1 then 2 else 1 end
where StudentId in (1,2)
如果你明确将删除的地址设置回修改
db.Entry(st1Addr).State = EntityState.Modified;
您会看到 SaveChanges 失败,因为它无法提出使数据库处于所需状态的一系列更改。
System.InvalidOperationException: '无法保存更改,因为 在要保存的数据中检测到循环依赖
所以直接修改 SudentAddress.StudentId 在这里没有帮助。
我认为通过更改跟踪器执行此操作的唯一方法是复制 StudentAddress 实体。然后两个旧的都将被删除并插入新的。
【讨论】:
以上是关于EF Core 一对一关系交换引用问题的主要内容,如果未能解决你的问题,请参考以下文章