5

Below example of one-to-one relationship throws an exception

public class User
{
    public int Id { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public User User { get; set; }
}

Exception says:

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

it works if i remove User property from Address but i don't want.

How can i have such a relationship without an exception ?

Freshblood
  • 6,285
  • 10
  • 59
  • 96

2 Answers2

14

While the answer provided by Eranga is correct and creates a shared primary key association between User and Address, you might not want to use it due to the limitations this mapping type has.

Here is another way of creating a 1:1 association which is called one-to-one foreign key association:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Address>()
                .HasRequired(a => a.User)
                .WithOptional(u => u.Address)
                .Map(m => m.MapKey("UserId"));
}

EF Code First recognizes this as a 1:1 association hence allowing you to have a bidirectional association between User and Address.

Now all you need to do is to define a Unique Key constraint on the UserId column to make your relationship a true one to one on your database side. One way for doing so is using a Seed method that has been overridden in a custom initializer class:

class DbInitializer : DropCreateDatabaseAlways<Context>
{
    protected override void Seed(Context context)
    {
        context.Database.ExecuteSqlCommand("ALTER TABLE Addresses ADD CONSTRAINT uc_User UNIQUE(UserId)");
    }
}


The above code will result in the following schema:

enter image description here

Morteza Manavi
  • 33,026
  • 6
  • 100
  • 83
4

You need to use fluent API to map the relationship as shared primary key.

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         modelBuilder.Entity<Address>()
             .HasRequired(a => a.User)
             .WithOptional(u => u.Address);
    }
}
Brandon
  • 68,708
  • 30
  • 194
  • 223
Eranga
  • 32,181
  • 5
  • 97
  • 96
  • I have exactly did what you have said and dbcontext created database without any problem. But when i check tables i see that there is no any relation between user and address tables. huhhh – Freshblood May 06 '12 at 11:24
  • @Freshblood The PK of `Address` should also be an FK to `User` table PK. – Eranga May 06 '12 at 11:36
  • I couldn't understand what i have to do – Freshblood May 07 '12 at 06:01
  • @Freshblood If you allow EF to create the database(eg: using an `IDatabaseInitializer`) it will create the FK mentioned above. – Eranga May 07 '12 at 06:19
  • @Erange Have you tried it ? I have tried in simple app and it did not created really. – Freshblood May 07 '12 at 06:58