Entity Framework 6 inverting column order for composite foreign keys

composite-key entity-framework-6

Question

I'm getting this error:

(15,10) : error 3015: Problem in mapping fragments starting at lines 6, 15: Foreign key constraint 'Beta_Alpha' from table Beta (Alpha_2, Alpha_1) to table Alpha (Alpha_1, Alpha_2):: Insufficient mapping: Foreign key must be mapped to some AssociationSet or EntitySets participating in a foreign key association on the conceptual side.

The key information is that the composite foreign key in Beta (Alpha_2, Alpha_1) has the columns inverted, with Alpha_2 first and Alpha_1 second. This appears to be a bug in Entity Framework.

Here are the entities:

public class Alpha
{
    [Key, Column(Order = 1)]
    public string Alpha_1 { get; set; }
    [Key, Column(Order = 2)]
    public string Alpha_2 { get; set; }
}

public class Beta
{
    [Key, Column(Order = 1)]
    public string Beta_1 { get; set; }
    [Key, Column(Order = 2)]
    public string Alpha_2 { get; set; }
    [Required]
    public string Alpha_1 { get; set; }

    [ForeignKey("Alpha_1, Alpha_2")]
    public virtual Alpha Alpha { get; set; }
}

Note that the ForeignKey attribute in Beta correctly lists Alpha_1 first.

Here is the Migration that's generated:

public partial class Test : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Betas",
            c => new
                {
                    Beta_1 = c.String(nullable: false, maxLength: 128),
                    Alpha_2 = c.String(nullable: false, maxLength: 128),
                    Alpha_1 = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => new { t.Beta_1, t.Alpha_2 })
            .ForeignKey("dbo.Alphas", t => new { t.Alpha_2, t.Alpha_1 }, cascadeDelete: true)
            .Index(t => new { t.Alpha_2, t.Alpha_1 });

        CreateTable(
            "dbo.Alphas",
            c => new
                {
                    Alpha_1 = c.String(nullable: false, maxLength: 128),
                    Alpha_2 = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => new { t.Alpha_1, t.Alpha_2 });

    }

    public override void Down()
    {
        DropForeignKey("dbo.Betas", new[] { "Alpha_2", "Alpha_1" }, "dbo.Alphas");
        DropIndex("dbo.Betas", new[] { "Alpha_2", "Alpha_1" });
        DropTable("dbo.Alphas");
        DropTable("dbo.Betas");
    }
}

Even if I manually update the Migration, I still get the error because the internal model itself is inverting the columns.

The bug appears to be related to the fact that Alpha_2 is also part of Beta's composite primary key.

Update Studying the link provided by Andrey Molotkov below, I removed the ForeignKey("Alpha_1, Alpha_2") attribute from Beta's Alpha property and tried to explicitly map it in the Fluent API, but it still had the exact same problem.

The next suggestion at that link was to explicitly set the order using the Column attribute. I think this gets to the crux of the problem. I have a property, Alpha_2, that is participating in a composite primary key, and a composite foreign key, so I would have to be able to specify the order for each key independently.

public class Beta
{
    [Key, Column(Order = 1)]
    public string Beta_1 { get; set; }
    [Key, Column(Order = 2), ForeignKey("Alpha"), Column(Order = 1)]
    public string Alpha_2 { get; set; }
    [Required, ForeignKey("Alpha"), Column(Order = 2)]
    public string Alpha_1 { get; set; }

    public virtual Alpha Alpha { get; set; }
}

But this causes an error because the Column attribute can only appear once.

I think EF needs a way to specify the Order directly in the Key or ForeignKey attribute.

1
3
7/24/2015 4:36:41 PM

Accepted Answer

You need to change the order of Beta foreign key columns:

public class Beta
{
    [Key, Column(Order = 1)]
    public string Beta_1 { get; set; }
    [Key, Column(Order = 3), ForeignKey("Alpha")]
    public string Alpha_2 { get; set; }
    [Required, ForeignKey("Alpha"), Column(Order = 2)]
    public string Alpha_1 { get; set; }

    public virtual Alpha Alpha { get; set; }
}
1
7/24/2015 5:50:47 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow