Skip to content

Extending CodeFirst (EntityFramework) to Multiple Levels of 1 to 1 Relationships (Strongly Typed)

Updated: at 05:05 PM

In my previous post, I showed how to take a simple relationship between Customers and an one Detail per customer build that into a relationship that eagerly loaded the customer record when retrieving a Detail record with CodeFirst in EntityFramework.  Now, let’s extend that so that a customer has an Address associated with them. This means, the relationship is as follows:

Detail

    Customer

        Address

Or, using my favorite Sql Manager Tool http://www.sqlmanager.net/ from EMS Database Management Solutions:

 

image

 

The model is now as follows:

namespace Con1
{
    public class SiteDB : DbContext
    {
        public DbSet<Detail> Details { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerAddress> CustomerAddresss { get; set; }
    <span class="kwrd">public</span> SiteDB(DbConnection connection)
        : <span class="kwrd">base</span>(connection, <span class="kwrd">true</span>)
    {
        <span class="rem">//ctor uses for tracing </span>
    }

    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnModelCreating(DbModelBuilder modelBuilder)
    {
    }


    <span class="kwrd">public</span> SiteDB()
    {
    }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> CustomerAddress
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    <span class="kwrd">public</span> <span class="kwrd">long</span> Id { get; set; }

    <span class="kwrd">public</span> <span class="kwrd">string</span> City { get; set; }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> Customer
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    <span class="kwrd">public</span> <span class="kwrd">long</span> Id { get; set; }

    [ForeignKey(<span class="str">&quot;CustomerAddressId&quot;</span>)]
    <span class="kwrd">public</span> CustomerAddress CustomerAddress { get; set; }

    <span class="kwrd">public</span> <span class="kwrd">long</span> CustomerAddressId { get; set; }

    <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; set; }

}

<span class="kwrd">public</span> <span class="kwrd">class</span> Detail
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    <span class="kwrd">public</span> <span class="kwrd">long</span> Id { get; set; }

    [ForeignKey(<span class="str">&quot;CustomerId&quot;</span>)]
    <span class="kwrd">public</span> Customer Customer { get; set; }

    <span class="kwrd">public</span> <span class="kwrd">long</span> CustomerId { get; set; }


    <span class="kwrd">public</span> <span class="kwrd">string</span> DetailDescription { get; set; }
}

}

And the code to actually retrieve the data is now as follows (notice the type safe and non type safe include syntax.  Both work, but of course I prefer the type safe.

 internal class Program
    {
        private static void Main(string[] args)
        {
            Database.SetInitializer(new SiteDBInitializer());
        <span class="kwrd">using</span> (var context = <span class="kwrd">new</span> SiteDB())
        {
            Console.WriteLine(context.Customers.Count());

            <span class="rem">//var details = context.Details.Include(&quot;Customer.CustomerAddress&quot;);</span>

            var details = context.Details.Include(o=&gt;o.Customer.CustomerAddress);

            <span class="kwrd">foreach</span> (var detail <span class="kwrd">in</span> details)
            {

Console.WriteLine( String.Format( “DetailId: {0} CustomerId: {1} Customer.Name: {2} Customer.Customeraddress.City: {3}”, detail.Id, detail.CustomerId, detail.Customer.Name, detail.Customer.CustomerAddress.City)); }

        }
    }
}

<span class="kwrd">internal</span> <span class="kwrd">class</span> SiteDBInitializer : CreateDatabaseIfNotExists&lt;SiteDB&gt;
{
    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Seed(SiteDB context)
    {
        context.Details.Add(<span class="kwrd">new</span> Detail
            {
                Customer =
                    <span class="kwrd">new</span> Customer {Name = <span class="str">&quot;pkellner&quot;</span>, CustomerAddress = <span class="kwrd">new</span> CustomerAddress {City = <span class="str">&quot;Hartsdale&quot;</span>}},
                DetailDescription = <span class="str">&quot;descr1&quot;</span>
            });

        context.SaveChanges();
    }
}</pre>

And the result running it is now:

image

HTH’s.