EF 一对一关系将实体与另一个关系更改(替换)

本文关键字:关系 替换 一对一 实体 EF 另一个 | 更新日期: 2023-09-27 18:34:58

我无法将实体一变一变:

这是我的测试类:

public class MyUser
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public virtual MyAddress MyAddress { get; set; }
}
public class MyAddress
{
    public Guid Id { get; set; }
    public string AddressLine { get; set; }
    public virtual MyUser MyUser { get; set; }
}

这是我的映射:

modelBuilder.Entity<MyAddress>().HasOptional(x => x.MyUser).WithRequired(x => x.MyAddress);

在数据库中,我有

MyUser ID = "abc", Name = "Test"
MyAddress ID = "abc", AddressLine = "TestAddress"
MyAddress ID = "dfg", AddressLine = "TestAddress2"

否,我想从具有相同ID的MyUser中删除MyAddress,并向MyUser添加具有其他ID的MyAddress

// myUser.Id = "abc" myUser.MyAddress.Id = "abc"
// myOldAddress.Id = "abc" myOldAddress.MyUser.Id = "abc"
// myNewAddress.Id = "dfg" myNewAddress.MyUser = null
var myUser = repoUser.GetById("abc")
var myOldAddress = repoAddress.GetById("abc");
myOldAddress.MyUser = null;
var myNewAddress = repoAddress.GetById("dfg");
myUser.MyAddress = myNewAddress;
myNewAddress.MyUser = myUser;
//on save I have this exception and what result i want to have
// myUser.Id = "abc" myUser.MyAddress.Id = "abc"
// myOldAddress.Id = "hjk" myOldAddress.MyUser = null
// myNewAddress.Id = "abc" myNewAddress.MyUser.Id = "abc"
// something like this (substitute)
Exception:
Additional information: A referential integrity constraint violation occurred: 
A primary key property that is a part of referential integrity constraint cannot be 
changed when the dependent object is Unchanged unless it is being set to the
 association's principal object. The principal object must be tracked and not
 marked for deletion.
{"A referential integrity constraint violation occurred: A primary key property
 that is a part of referential integrity constraint cannot be changed when the 
dependent object is Unchanged unless it is being set to the association's 
principal object. The principal object must be tracked and not marked for deletion."}

为什么 EF 不会自动将 ID 更改为与用户 ID 相同?用户必须具有地址 1:1,但地址具有可选的用户 1:0

EF 一对一关系将实体与另一个关系更改(替换)

首先,我不相信用户之间关系的设计 和地址是一对一的,不允许没有用户的地址 同时不允许没有地址的用户。因为通常一个典型的用户可以有很多地址


但是,根据我们在评论部分的讨论,我得到了以下内容:

数据库中的地址表有 2 列: 不允许AddressLine ID

因此,当您在代码中调用myOldAddress.MyUser = null;时您只需让 EF 将Address.Id设置为数据库中违反数据库约束的null

我不建议的一种解决方案是让Address.Id允许null

但我建议将设计更改为以下之一:

  • 使用除 UserId 之外的单独唯一键标识地址表
  • 创建一个列来保存相关的 userId 并使其允许空

因此,您的地址表将如下所示:

ID (not null)
AddressLine 
UserId (Nullable) forieng key in User Table

这样,您就可以安全地将MyAddress.MyUser设置为null

代码

从代码示例中,当前未设置 myOldAddress.MyUser 属性。你能试着把那行注释掉吗

var myUser = repoUser.GetById("abc")
var myOldAddress = repoAddress.GetById("abc");
//myOldAddress.MyUser = null;
var myNewAddress = repoAddress.GetById("dfg");
myUser.MyAddress = myNewAddress;

由于用户字段在地址实体上是可选的,因此如果之前未设置它,则无需将其设置为 null。