实体框架,具有 2 个外键到 2 个不同表的表

本文关键字:框架 具有 实体 | 更新日期: 2023-09-27 18:29:17

>我有 3 个模型,其中包含如下字段:

public class RootObject
{
    [Key]
    public int RootObjectId { get; set; }
    [ForeignKey("RootObjectId")]
    public virtual AObject AObject { get; set; }
    [ForeignKey("RootObjectId")]
    public virtual BObject BObject { get; set; }
    public string Name { get; set; }
}
public class AObject
{
    [Key]
    public int AObjectId { get; set; }
    //Other fields
}
public class BObject
{
    [Key]
    public int BObjectId { get; set; }
    //Other fields
}

我想要它,以便如果我目视检查RootObject表,我会看到RootObjectIdName的列表。 为方便起见,让我们假设偶数RootObjectId映射到AObjectId,赔率映射到BObjectId。 如果我目视检查AObject,我希望看到ID的2,4,6,...那是 FK 的RootObject. 如果要目视检查BObject,我希望看到ID的1,3,5,...那是 FK 的 RootObject .

目前,当我尝试这种方法时,出现以下错误:

"更新条目时出错...参照完整性约束冲突。依赖角色具有多个具有不同值的主体。

我试图删除 RootObject 中的 FK 属性,但这在 RootObject 中创建了 2 个填充了 ID 号的列。 我不希望这样,因为每个RootObject都有一个AObject或一个BObject. 它不能两者兼而有之。

实体框架,具有 2 个外键到 2 个不同表的表

对我来说,您正在寻找实体框架中的 TPT(每种类型表(方法可能是一种解决方案的东西。应用于您的情况(有很多方法,但我测试过并且有效(:

public class RootObject
{
    [Key]
    public int RootObjectId { get; set; }
    public string Name { get; set; }
}
[Table("AObjects")]
public class AObject : RootObject
{
    //Other fields
    public string AField { get; set; }
}
[Table("BObjects")]
public class BObject : RootObject
{
    //Other fields
    public string BField { get; set; }
}

对于 DbContext 类:

public DbSet<RootObject> RootObjects { get; set; }
public DbSet<AObject> AObjects { get; set; }
public DbSet<BObject> BObjects { get; set; }

种子示例:

AObject a1 = new AObject() { Name = "ImA", AField = "adata" };
BObject b1 = new BObject() { Name = "ImB", BField = "bdata" };
context.AObjects.Add(a1);
context.BObjects.Add(b1);
context.SaveChanges();

我认为不可能使用一列作为两个不同表的外键。您应该考虑两个(可选(FK,例如:

public class RootObject
{
    [Key]
    public int RootObjectId { get; set; }
    public int? EvensAObjectId { get; set; }
    public int? OddsBObjectId { get; set; }
    [ForeignKey("EvensAObjectId")]
    public virtual AObject AObject { get; set; }
    [ForeignKey("OddsBObjectId")]
    public virtual BObject BObject { get; set; }
    public string Name { get; set; }
}

要设置 1-0..1 关系,您需要在模型配置期间显式定义关系。

public class Model1 : DbContext
{
    public Model1()
        : base("name=Model1")
    {
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AObject>()
            .HasRequired(e => e.RootObject).WithOptional(r => r.AObject);
        modelBuilder.Entity<BObject>()
            .HasRequired(e => e.RootObject).WithOptional(r => r.BObject);
        base.OnModelCreating(modelBuilder);
    }
    public virtual DbSet<RootObject> RootObjects { get; set; }
    public virtual DbSet<AObject> AObjects { get; set; }
    public virtual DbSet<BObject> BObjects { get; set; }
}

public class RootObject
{
    [Key]
    public int RootObjectId { get; set; }
    public virtual AObject AObject { get; set; }
    public virtual BObject BObject { get; set; }
    public string Name { get; set; }
}
public class AObject
{
    [Key]
    public int AObjectId { get; set; }
    public virtual RootObject RootObject { get; set; }
}
public class BObject
{
    [Key]
    public int BObjectId { get; set; }
    public virtual RootObject RootObject { get; set; }
}

设置RootObject.AObjectRootObject.BObject时,您需要非常小心,因为如果已经有相关的行,则在保存时会出现错误。此外,我认为没有任何方法可以让 EF 强制执行约束,即每个 RootObject 必须具有 AObject 或 BObject,但不能同时具有两者 - 您需要在代码中强制执行这一点。