实体框架,包含2个不同表的{2}个外键的表

时间:2016-01-06 18:11:07

标签: c# mysql entity-framework

我有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,......是RootObject的FK。如果要视觉检查BObject,我希望看到ID为1,3,5,......是RootObject的FK。

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

“更新条目时发生错误...参照完整性约束违规。从属角色具有多个具有不同值的主体。”

我尝试删除RootObject中的FK属性,但在RootObject中创建了2个用ID编号填充的其他列。我不希望这样,因为每个RootObject都有一个AObject或一个BObject。它不能兼得。

3 个答案:

答案 0 :(得分:1)

对我而言,您正在寻找实体框架中的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();

答案 1 :(得分:0)

我认为不可能将一列用作两个不同表的外键。您应该考虑两个(可选)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; }
}

答案 2 :(得分:0)

要设置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,而不是两者 - 您需要在代码中强制执行该操作。