277
public class Foo
{
    public string FooId{get;set;}
    public Boo Boo{get;set;}
}


public class Boo
{
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

I was trying to do this in Entity Framework when I got the error:

Unable to determine the principal end of an association between the types 'ConsoleApplication5.Boo' and 'ConsoleApplication5.Foo'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

I have seen questions on StackOverflow with a solution for this error, but I want to understand what the term "principal end" means.

taher chhabrawala
  • 4,110
  • 4
  • 35
  • 51

3 Answers3

384

In one-to-one relation one end must be principal and second end must be dependent. Principal end is the one which will be inserted first and which can exist without the dependent one. Dependent end is the one which must be inserted after the principal because it has foreign key to the principal.

In case of entity framework FK in dependent must also be its PK so in your case you should use:

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

Or fluent mapping

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • thanks, now i also understood the "foreign key vs independent association" article on your blog :) – taher chhabrawala Jun 30 '11 at 09:54
  • 6
    @Ladislav, I need to make two independant tables that both have an optional reference to each other (one to one), I want them both to have their own PKs each, how is this possible? I posted a [separate question](http://stackoverflow.com/questions/13609507/optional-one-to-one-relationship). – Shimmy Weitzhandler Nov 28 '12 at 16:15
  • 10
    You have no idea how many hours it took to find an answer to this - ms documentation is POOOOOOP ty. – gangelo May 15 '13 at 17:25
  • 1
    Note you may need to add using System.ComponentModel.DataAnnotations.Schema; to get ForeignKey in VS2012 – Stuart Dobson Jun 28 '13 at 23:37
  • 2
    Does that mean that `Foo` is the principal then? – bflemi3 Nov 17 '13 at 19:04
  • 8
    @bflemi3 you are correct `Boo` is the dependent, requires a `Foo`, and gets the foreign key. `Foo` is the principal and can exist without a `Boo`. – Colin Nov 18 '13 at 10:07
  • [Foreign key vs. Independent associations in EF 4](http://www.ladislavmrnka.com/2011/05/foreign-key-vs-independent-associations-in-ef-4/) – sparebytes Feb 20 '14 at 14:49
  • 1
    @Ladislav 'In case of entity framework FK in dependent must also be its PK' does this argument still stand in EF 6 ? – sm_ Jun 21 '16 at 04:15
  • 1
    @SirajMansour: Yes it does. – Ladislav Mrnka Jun 21 '16 at 10:15
  • 1
    @LadislavMrnka so my only option is using the 'Required' attribute in case the FK is not the pk in the depenedant ? – sm_ Jun 21 '16 at 11:07
  • Worth mentioning that both keys can be required in a 1-1 relationship but the notion of Principal and Dependent entity is still valid, in which case you would choose the following Fluent API option: `modelBuilder.Entity().HasRequired(f => f.Boo).WithRequiredPrincipal(s => s.Foo);` – GDS Aug 12 '16 at 02:36
  • 1
    @LadislavMrnka What if you have the same scenario but need the FK in a different field which is not the PK ? How would you do that ? – CodeEngine Nov 09 '16 at 20:37
  • 1
    I have a similar question as earlier: does the requirement of the dependent FK being the same as the PK still hold true for EF Core? Based on the example of one-to-one mappings in https://learn.microsoft.com/en-us/ef/core/modeling/relationships (see toward the bottom with Blog and BlogImage), it appears the dependent maintains a seperate FK from it's PK. It doesn't mention it explicitly, but there's no attributes or mapping indicating FK and PK are both the same. – Derek Greer Feb 19 '19 at 04:26
187

You can also use the [Required] data annotation attribute to solve this:

public class Foo
{
    public string FooId { get; set; }

    public Boo Boo { get; set; }
}

public class Boo
{
    public string BooId { get; set; }

    [Required]
    public Foo Foo {get; set; }
}

Foo is required for Boo.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • This was correct for my following code where I wanted a map between the two as a separate entity public class Organisation { public int Id { get; set; }} public class user { public int Id { get; set; }} public class UserGroup { [Key] public int Id { get; set; } [Required] public virtual Organisation Organisation { get; set; } [Required] public virtual User User { get; set; } } – AndyM Jul 10 '14 at 12:54
  • I'm using Oracle and none of the fluent api's worked for me. Thanks bro. So simple. – CameronP Aug 06 '14 at 17:55
  • 11
    Be aware that when using this solution you will get validation exceptions when you try and update a `Boo` that you just retrieved from the database, unless you first trigger the lazy-load of the `Foo` property. https://entityframework.codeplex.com/SourceControl/network/forks/BrandonDahler/EntityFramework/contribution/7703 – NathanAldenSr Mar 07 '15 at 03:56
  • 2
    shouldn't `Boo Boo` be virtual then? – Simon_Weaver Jan 14 '17 at 04:45
  • 1
    @NathanAldenSr the link is bad now, how do you make that change? – CamHart Apr 25 '18 at 22:19
  • Configuring via FluentAPI wasn't working, still not sure why - but adding `Required` to the primary's property in the dependent class worked. – JeremyW May 14 '21 at 18:46
9

This is with reference to @Ladislav Mrnka's answer on using fluent api for configuring one-to-one relationship.

Had a situation where having FK of dependent must be it's PK was not feasible.

E.g., Foo already has one-to-many relationship with Bar.

public class Foo {
   public Guid FooId;
   public virtual ICollection<> Bars; 
}
public class Bar {
   //PK
   public Guid BarId;
   //FK to Foo
   public Guid FooId;
   public virtual Foo Foo;
}

Now, we had to add another one-to-one relationship between Foo and Bar.

public class Foo {
   public Guid FooId;
   public Guid PrimaryBarId;// needs to be removed(from entity),as we specify it in fluent api
   public virtual Bar PrimaryBar;
   public virtual ICollection<> Bars;
}
public class Bar {
   public Guid BarId;
   public Guid FooId;
   public virtual Foo PrimaryBarOfFoo;
   public virtual Foo Foo;
}

Here is how to specify one-to-one relationship using fluent api:

modelBuilder.Entity<Bar>()
            .HasOptional(p => p.PrimaryBarOfFoo)
            .WithOptionalPrincipal(o => o.PrimaryBar)
            .Map(x => x.MapKey("PrimaryBarId"));

Note that while adding PrimaryBarId needs to be removed, as we specifying it through fluent api.

Also note that method name [WithOptionalPrincipal()][1] is kind of ironic. In this case, Principal is Bar. WithOptionalDependent() description on msdn makes it more clear.

Patrick
  • 1,717
  • 7
  • 21
  • 28
Sudarshan_SMD
  • 2,549
  • 33
  • 23
  • 2
    What if you actually *want* the `PrimaryBarId` property? This is ridiculous to me. If I add the property and say it's the foreign key, I get an error. But if I don't have the property, then EF will create it anyways. What's the difference? – Chris Pratt Jun 29 '17 at 16:37
  • 1
    @ChrisPratt This might not sound reasonable. I arrived at this solutions after trail and error. Was not able to configure one-to-one mapping when I had `PrimayBarId` property in `Foo` entity. Likely the same solution that you tried. Limitations in EF perhaps? – Sudarshan_SMD Jun 30 '17 at 06:42
  • 3
    Yeah, it is. I've come to find out that EF to this day has never implemented unique indexes. As a result, the only way available to map a one-to-one is to use the primary key of the principal end as the primary key of the dependent end, because a primary key is by nature unique. In other words, they half-implemented it and took a shortcut that dictates that your tables have to be design in a non-standard way. – Chris Pratt Jun 30 '17 at 13:42