【问题标题】:EF Core one-to-one relationship swapping references issueEF Core 一对一关系交换引用问题
【发布时间】: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 核心实现这一目标?

【问题讨论】:

  • 能否分享两条记录的底层数据?

标签: c# .net entity-framework orm one-to-one


【解决方案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 实体。然后两个旧的都将被删除并插入新的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-25
    • 2017-10-26
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多