EF Core 一对一关系交换引用问题

EF Core one-to-one relationship swapping references issue

我有两个实体

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 保存更改时,其中一个学生地址记录将从数据库中删除。

我需要更改对学生地址的引用。如何使用 EF 核心实现此目的?

因为是1-1的关系,一设置就

 student1.Address = st2Addr;

student1 的旧地址必须删除,因为它会违反 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: 'Unable to save changes because a circular dependency was detected in the data to be saved

所以直接修改 SudentAddress.StudentId 在这里无济于事。

我认为通过更改跟踪器执行此操作的唯一方法是复制 StudentAddress 实体。然后旧的都删除,新的插入。