无法确定相关操作的有效排序循环引用

时间:2015-09-24 00:34:39

标签: c# entity-framework

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

在我保存具有关系的实体的代码中,我在到达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是必需的。

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

以下是流畅的API代码:

modelBuilder.Entity<Shipment>()
    .HasOptional<ShipmentNumber>((shipment) => shipment.ShipmentNumber)
    .WithMany();

装运有一个&#34; true&#34; ShipmentNumber,但许多ShipmentNumbers可以链接到同一个Shipment,因此WithMany()调用(没有navigator属性的关系)。从理论上讲,这两种关系应该总是返回一个实体,但我知道EF不会在这里允许我1:1的关系,所以我使用了可选项。

这是实际的代码:

shipment = tracker.Shipment;

ctx.Shipments.Add(shipment);
shipment.ShipmentNumber = new ShipmentNumber { Number = tracker.ShipmentNumber };

ctx.ShipmentNumbers.Add(shipment.ShipmentNumber);

ctx.SaveChanges();

如果有人知道如何正确保存实体以及关系,请告诉我们。我此刻完全陷入困境。

1 个答案:

答案 0 :(得分:2)

好吧,我不知道为什么你想要数据库中的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时,如果需要,所有依赖对象都将插入数据库。