7

I have a parent entity and a child entity.

In the DB the primary key for parent is p_p_id and the foreign key in the child is the same p_p_id

There is no foreign key constraint in the database.

The entities have the properties set up in their respective classes pointing at each other.

Parent Class

public virtual ChildProject ThisChildProject { get; set; }

Child Class

public virtual ParentProject ThisParentProjection { get; set; }

There are no annotations on these properties nor on the Ids of either class.

In the config, I tried to do the mapping in the child.

HasRequired(i => i.ThisParentProject).WithOptional(o => o.ThisChildProject );

What happens is EF tries to map using the primary key of the child and the primary key of the parent.

But I want to use a defined FK in the child and the primary key of the parent

Smeegs
  • 9,151
  • 5
  • 42
  • 78

2 Answers2

9

By default EF uses so called Shared Primary Key Association which uses the dependent entity PK as FK to the principal entity.

You can override that behavior by specifying the hidden (shadow) FK name through Map -> MapKey fluent configuration:

HasRequired(e => e.ThisParentProject)
   .WithOptional(e => e.ThisChildProject)
   .Map(m => m.MapKey("p_p_id"));

Update: Please note the hidden (shadow) word. EF does not support explicit FK property for this type of relationship - there is no HasForeignKey fluent method and putting ForeignKey attribute leads to error. So if you have something like this in your ChildProject class:

[Column("p_p_id")]
public int ThisParentProjectId { get; set; }

I'm afraid the only option is to remove it and work only with navigation properties.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • 1
    Hmmm. that throws the following exception `p_p_id: Name: Each property name in a type must be unique. Property name 'p_p_id' is already defined.` – Smeegs Mar 27 '17 at 18:12
  • Ah, so you have **explicit** FK field like `public int p_p_id { get; set; }`. This is what I meant in the first comment - it's not supported (no `HasForeignKey` method), you should remove the explicit field and leave only the navigation property. – Ivan Stoev Mar 27 '17 at 18:15
  • Hmmm. I have to define the mapping because the property in the class isn't the same name as the column. – Smeegs Mar 27 '17 at 18:29
  • No. `Map` methods are used to name the hidden properties representing table columns. `HasKey`, `HasForeignKey` etc. methods with lambda argument are for mapping existing properties of the class. Again, this relationship does not allows having primitive (id like) property representing the db table FK column in the class. I've been fighting this issue many times, so simply there is no other solution than sacrificing something. If you ask why, I don't know - EF team decision. – Ivan Stoev Mar 27 '17 at 18:35
  • Thanks. I'll have to look into this. I'm not sure if ripping out the property is a viable option. I may have to rethink the design. – Smeegs Mar 27 '17 at 20:00
0

Depending on your property names, you may need to add an ForeignKey attribute, but the standard collection declaration is fine:

http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

And here is One-One as requested by your updated question:

http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Mike_G
  • 16,237
  • 14
  • 70
  • 101
  • When I try the second options I get the following message `Multiplicity is not valid in Role '' in relationship ''. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'. ` – Smeegs Mar 27 '17 at 17:58