1

I am trying to set up a bi-directional one-to-one relationship. However, I am failing to get a bi-directional setting for two entities.

For example, lets say one person has one phone number, and one phone number can only be associated to one person. I would have:

  public class Person : Entity
  {
    public long PersonId { get; set; }
    public virtual PhoneNumber PhoneNumber {get; set; }
  }

  public class PhoneNumber : Entity
  {
    public long PhoneNumberId { get; set; }
  }

However, with this re-arrangement, I cannot get a bi-directional setting. i.e. I cannot have phoneNumber.Person.


What I have tried:

  public class PhoneNumber : Entity
  {
    public long PhoneNumberId { get; set; }

    [InverseProperty("PersonId")]
    public virtual Person Person {get; set; }
  }

This does not seem to work when I execute the following code:

   var realNumber = new PhoneNumber();
   var person = new Person() {PhoneNumber = realNumber};
   context.SaveChanges();

Here, the PhoneNumber entity has a column Person (set to NULL), and the person has a column for PhoneNumber (has value).

Karan
  • 14,824
  • 24
  • 91
  • 157
  • 1
    EF requires that both entities share the same primary key for a 1:1, thus you should name them the same (for convention purposes). – Erik Funkenbusch Oct 02 '12 at 17:04
  • @MystereMan That is actually just one of 2 ways to get a 1:1 in EF. http://stackoverflow.com/a/10837964/176877 – Chris Moschini Mar 30 '13 at 08:54
  • @ChrisMoschini - Huh? Both of those methods have a shared primary key. I don't understand your point, nor does it contradict what I said. – Erik Funkenbusch Mar 30 '13 at 10:33
  • @MystereMan I took shared PK to mean they had to have the same Property for their Key in their Entity mapping (which, they don't). You can set up 2 classes one-to-one without this. But, in that setup they do share primary key values in the database, so if that's what you meant you were correct. – Chris Moschini Mar 30 '13 at 10:45
  • @ChrisMoschini - No, I said that they should be named the same for convention purposes, but if you prefer configuration over convention then you can name then anything. – Erik Funkenbusch Mar 30 '13 at 11:47

1 Answers1

2

This works for me

namespace Ef1to1
{
    public class TestContext : DbContext
    {

        public TestContext()
            : base("Data Source=127.0.0.1;database=Junk;Integrated Security=SSPI;")
        {

        }
        public DbSet<Person> Persons { get; set; }
        public DbSet<PhoneNumber> PhoneNumbers { get; set; }
    }
    [Table("Person")]
    public class Person 
    {
        [Key, Column("PersonId")]
        public long Id { get; set; }

        public virtual PhoneNumber phoneNumber { get; set; }
    }

    [Table("PhoneNumber")]
    public class PhoneNumber
    {

        [Key, Column("PhoneNumberId"), ForeignKey("person")]
        public long Id { get; set; }

        public virtual Person person { get; set; }
    } 

   public class Program
    {

        static void Main(string[] args)
        {
            var realNumber = new PhoneNumber();
            var person = new Person() { phoneNumber = realNumber }; 
            var context = new TestContext();

            context.Persons.Add(person) ;
            context.SaveChanges();
            ;

        }
    }
}
Gratzy
  • 9,164
  • 4
  • 30
  • 45
  • hmm... i get a "Unable to determine the principal end of an association between the types" – Karan Oct 02 '12 at 16:04
  • so the PhoneNumberId will also be the foreignkey to Person? Not sure if that makes sense, but will try it out now ... – Karan Oct 02 '12 at 16:15
  • i dont think that did it. I think having set ForeignKey Person to PhoneNumberId tells EF that the id of PhoneNumber and Person should match. Ie. Person.Id = 1 should have PhoneNumber.Id = 1. Just a thought ... might be wrong ... – Karan Oct 02 '12 at 16:24
  • @Karan after about 100 edits I think this should work for you – Gratzy Oct 02 '12 at 20:08
  • thanks! I do not have my coding environment here atm, I will give it a try first thing tomorrow morning! :) – Karan Oct 02 '12 at 20:33
  • @Karan I don't know your table structure so you might have to modify – Gratzy Oct 02 '12 at 21:57
  • Note that the Column attributes aren't necessary for this approach to work. The Key attributes are also inferred because the properties are named Id. – Chris Moschini Mar 30 '13 at 09:44