无法确定从属操作循环引用的有效顺序
本文关键字:有效 顺序 引用 循环 操作 无法确定 | 更新日期: 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
时,所有的依赖对象将被插入到数据库中,如果需要的话。