Entity Framework 4.1 – One To One Mapping

In the snippet below you can see that a customer has an address property.

    public class Customer
    {
        public Customer()
        {
           Address = new Address();
        }
 
        public Guid Id { get; set; }
        public string Name { get; set; }
        public Address Address { get; set; }
        public Guid AddressId { get; set; }
    }
 
    public class Address
    {
        public Guid Id { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Street { get; set; }
    }

The database that gets generated though defines this as a one to many relationship.

Which is not what you’re expecting, or is it? I haven’t defined any restrictions on the address class so indeed an address could be shared between multiple customers. Let’s change that.

    public class Customer
    {
        public Customer()
        {
           Address = new Address();
        }
 
        public Guid Id { get; set; }
        public string Name { get; set; }
        public Address Address { get; set; }
 
    }
 
    public class Address
    {
        public Guid Id { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Street { get; set; }
        [Required]
        public Customer Customer { get; set; }
    }

I’ve added a navigation property from Address to Customer and marked the Customer property as required. This basically is telling EF that there is a one to one mapping between the two and the primary key of the customer should be used in the relationship. The primary key of the customer will also become the primary key of the address. If you did not add the required attribute you’ll get an invalidoperationexception saying that it’s unable to determine the principal end of an association.

You can also use the fluent api.

    public  class  CustomerContext
        : DbContext
    {
        public IDbSet<Customer> Customers { get; set; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Address>().HasRequired(x => x.Customer);
            base.OnModelCreating(modelBuilder);
        }
 
    }

They both result in the same database structure.

What if both ends are required? A customer always has an address and an address always has a customer. Marking both ends as required will again result in the same exception as before.

In order to model this you have to use the fluent api and there are two ways to achieve the desired result.

    public  class  CustomerContext
        : DbContext
    {
        public IDbSet<Customer> Customers { get; set; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Address>()
                .HasRequired(x => x.Customer)
                .WithRequiredDependent(x => x.Address);
            base.OnModelCreating(modelBuilder);
        }
    }

I’m saying here that the address entity has a required customer property and that the customer class is actually in charge, MSDN reference.

Resulting database structure:

Another way to achieve the same result:

    public  class  CustomerContext
        : DbContext
    {
        public IDbSet<Customer> Customers { get; set; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Address>()
                .HasRequired(x => x.Customer)
                .WithRequiredDependent();
            modelBuilder.Entity<Customer>()
                .HasRequired(x => x.Address)
                .WithRequiredPrincipal();
            base.OnModelCreating(modelBuilder);
        }
    }

MSDN link on WithRequiredPrincipal.

You saw that the WithRequiredPrincipal and Depedant actually have one taking a lambda and one with no arguments. This allows you to exclude a navigation property and still get a proper one to one mapping. Which brings me back to my starting point.

public class Customer
    {
        public Customer()
        {
           Address = new Address();
        }
 
        public Guid Id { get; set; }
        public string Name { get; set; }
        public Address Address { get; set; }
    }
 
    public class Address
    {
        public Guid Id { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Street { get; set; }
 
 
    }
 
    public  class  CustomerContext
        : DbContext
    {
        public IDbSet<Customer> Customers { get; set; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Customer>()
                .HasRequired(x => x.Address)
                .WithRequiredPrincipal();
            base.OnModelCreating(modelBuilder);
        }
    }

20 Replies to “Entity Framework 4.1 – One To One Mapping”

  1. How to display on the web i.e i mean calling the function in the Controller action explain that also..given a Customer Id it should display the both related rows from Customer and Address

  2. That’s fine except Address never gets saved to the database since there is no DBSet for it in the Context (first of the both ends required scenarios, I never tried the other).

  3. Hi, i`v used this approeach but when i see in database there is not a column created customer for Address.
    in fact when i want to retrive data it says ” null reference exception”.
    may you help me?

  4. Thanks. And if i need to build one-to-one realationship between 2 tables with 2 keys ?
    For Example
    Customers (Id1 (key),id2(key),Name)
    Addresses (Id1 (key),id2(key),City,Country,Street)

  5. What about that case if I need two Adress field for the customer.
    Customer
    —> PrivateAdress
    —> FirmAdress

    ??

  6. What if I don’t want bidirection navigation e.g. Customer is my aggregate root nor foreign key properties like AddressId?

    1. What if the Address navigation property on Customer class is optional? Is there a way to do this using attributes?

  7. hi .
    i have a problem. please help me .
    how can i have a one-to-one relationship between a primarykey from a product table (for example) and non-primarykey from information (for example) in code first ?

Leave a Reply to an phu Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.