无法确定从属操作循环引用的有效顺序

本文关键字:有效 顺序 引用 循环 操作 无法确定 | 更新日期: 2023-09-27 18:14:10

我已经浪费了两天时间试图解决这个问题,但还没有找到解决方案。

在我的代码中,保存具有关系的实体,当到达ctx.SaveChanges()时,我得到这个错误:

无法确定相关操作的有效顺序。依赖关系可能由于外键约束而存在需求,或者存储生成的值。

Shipment.cs

[ForeignKey("ShipmentNumber")]
public int? DefaultShipmentNumber { get; set; }
public virtual ShipmentNumber ShipmentNumber { get; set; }

ShipmentNumber.cs

[Column("shipment_id")]
[ForeignKey("Shipment")]
public byte ShipmentId { get; set; }
public virtual Shipment Shipment { get; set; }

为了避免循环引用,属于Shipment的ShipmentNumber是可空的(可选的),而ShipmentNumber对Shipment的依赖是必需的。

我首先创建一个Shipment,添加它,然后将ShipmentNumber附加到它,并将其添加到表中。

下面是流畅的API代码:
modelBuilder.Entity<Shipment>()
    .HasOptional<ShipmentNumber>((shipment) => shipment.ShipmentNumber)
    .WithMany();

Shipment有一个"真实的"ShipmentNumber,但是许多ShipmentNumber可以链接到同一个Shipment,因此WithMany()调用(没有navigator属性的关系)。理论上,这两个关系应该总是返回一个实体,但是我知道EF不允许我在这里使用1:1的关系,所以我使用optional。

下面是实际代码:
shipment = tracker.Shipment;
ctx.Shipments.Add(shipment);
shipment.ShipmentNumber = new ShipmentNumber { Number = tracker.ShipmentNumber };
ctx.ShipmentNumbers.Add(shipment.ShipmentNumber);
ctx.SaveChanges();

如果有人知道如何正确地保存实体和关系,请告诉我。我现在完全卡住了。

无法确定从属操作循环引用的有效顺序

好吧,我不知道为什么你想要一个1:1:n的关系在数据库和1:0.1的关系在模型。

案例1

如果你想建立一个1:1的关系,你应该这样声明你的模型:

public class Shipment
{
    public int ShipmentId { get; set; }  
    //NO FK here
    public virtual ShipmentNumber ShipmentNumber { get; set; }
}
public class ShipmentNumber
{
    public int ShipmentId { get; set; } //ShipmentNumber PK is Also Shipment FK
    public virtual Shipment Shipment { get; set; }
}

映射:

modelBuilder.Entity<Shipment>()
    .HasKey(i => i.ShipmentId);
modelBuilder.Entity<ShipmentNumber>()
    .HasKey(i => i.ShipmentId);
modelBuilder.Entity<Shipment>()
    .HasRequired(i => i.ShipmentNumber)
    .WithRequiredPrincipal(i => i.Shipment)
    .WillCascadeOnDelete(false);
生成迁移:

CreateTable(
    "dbo.Shipments",
    c => new
        {
            ShipmentId = c.Int(nullable: false, identity: true),
        })
    .PrimaryKey(t => t.ShipmentId);
CreateTable(
    "dbo.ShipmentNumbers",
    c => new
        {
            ShipmentId = c.Int(nullable: false),
        })
    .PrimaryKey(t => t.ShipmentId)
    .ForeignKey("dbo.Shipments", t => t.ShipmentId)
    .Index(t => t.ShipmentId);

案例2

如果你想建立一个1:n的关系:

public class Shipment
{
    public int ShipmentId { get; set; }
    public virtual ICollection<ShipmentNumber> ShipmentNumbers { get; set; }
}
public class ShipmentNumber
{
    public int ShipmentNumberId { get; set; }
    public int ShipmentId { get; set; }
    public virtual Shipment Shipment { get; set; }
}

映射:

modelBuilder.Entity<Shipment>()
    .HasKey(i => i.ShipmentId);
modelBuilder.Entity<ShipmentNumber>()
    .HasKey(i => i.ShipmentNumberId);
modelBuilder.Entity<Shipment>()
    .HasMany(i => i.ShipmentNumbers)
    .WithRequired(i => i.Shipment)
    .HasForeignKey(i => i.ShipmentId)
    .WillCascadeOnDelete(false);
生成迁移:

CreateTable(
    "dbo.Shipments",
    c => new
        {
            ShipmentId = c.Int(nullable: false, identity: true),
        })
    .PrimaryKey(t => t.ShipmentId);
CreateTable(
    "dbo.ShipmentNumbers",
    c => new
        {
            ShipmentNumberId = c.Int(nullable: false, identity: true),
            ShipmentId = c.Int(nullable: false),
        })
    .PrimaryKey(t => t.ShipmentNumberId)
    .ForeignKey("dbo.Shipments", t => t.ShipmentId)
    .Index(t => t.ShipmentId);

另一个问题是你用来向数据库添加项目的代码。

ctx.Shipments.Add(shipment);
shipment.ShipmentNumber = new ShipmentNumber { Number = tracker.ShipmentNumber };
//this line is not necessary
ctx.ShipmentNumbers.Add(shipment.ShipmentNumber);
ctx.SaveChanges();

当你添加一个新的Shipment时,所有的依赖对象将被插入到数据库中,如果需要的话。