Entity Framework relationship with two foreign keys

.net c# ef-fluent-api entity-framework entity-framework-6

Question

I'm having a problem with connecting two tables in FluentAPI. It's in fact a mix of FluentAPI and Data Annotations. I Looked at this question but It didn't help me. I tried with Index, composed unique keys.

Basically Foo is the main table. Bar table is optional. The are connected via two columns. key1 and key2 pairs are unique. Think of it as a parent-child relationship with a restriction that 1 parent can have only 1 child:

Data Entities looks like this:

[Table("foo")]
public class Foo
{
    [Key]
    [Column("pk", TypeName = "int")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int FooId { get; set; }

    [Column("key1", TypeName = "int")]
    public int Key1 { get; set; }
    [Column("key2", TypeName = "int")]
    public int Key2 { get; set; }

    public Bar Bar { get; set; }
}

[Table("bar")]
public class Bar
{
    [Key]
    [Column("key1", TypeName = "int", Order = 1)]
    public int Key1 { get; set; }
    [Key]
    [Column("key2", TypeName = "int", Order = 2)]
    public int Key2 { get; set; }

    public Foo Foo { get; set; }
}    

Here's how I was trying to connect them:

modelBuilder.Entity<Bar>().HasRequired(p => p.Foo).WithOptional(p => p.Bar);

What is wrong? Bar DOES require Foo. Foo DOES have optional Bar. <--- this should be totally enough, because Foo has columns named exactly like primary keys in Bar. But it doesn't work.

So I tried specifying foreign keys:

modelBuilder.Entity<Bar>().HasRequired(p => p.Foo).WithOptional(p => p.Bar).Map(p => p.MapKey(new[] { "key1", "key2" }));

It says:

"The number of columns specified must match the number of primary key columns"

Whaaaat? how? how come? Uhh..

I also tried:

modelBuilder.Entity<Bar>().HasIndex(table => new { table.Key1, table.Key2 });  

So my questions are:

  1. Why my solution doesn't work? I do have complex key specified

  2. How can I slove it?

1
0
5/3/2018 6:26:38 PM

Popular Answer

This is going to be a little complicated, and I might be completely wrong here, but from my experience EntityFramework relations don't work that way. It seems to me that if Foo is required and Bar is optional, then each Bar should have a way to join back to Foo uniquely based upon Foo's pk value.

That is to say that Bar should be defined as:

[Table("bar")]
public class Bar
{
    [Key]
    [Column("key1", TypeName = "int", Order = 1)]
    public int Key1 { get; set; }
    [Key]
    [Column("key2", TypeName = "int", Order = 2)]
    public int Key2 { get; set; }
    public int FooId { get; set; }

    public Foo Foo { get; set; }
}    

You would then need to use this FooId in your description of the relationship, not the composite key contained in Bar. EntityFramework has always required me to join on the entire primary key of the parent POCO, which must be a foreign key of the child POCO. You may still be able to join through the child's key in LINQ queries.

0
5/3/2018 9:17:30 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