How to declare one to one relationship using Entity Framework 4 Code First (POCO)

Three methods:

A) Declare both classes with navigation properties to each other. Mark one of the tables (the dependent table) with the ForeignKey attribute on its Primary Key. EF infers 1-to-1 from this:

public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

​public class OpenIdInfo
{
    [ForeignKey("AppUser")]
    public int Id { get; set; }

    public string OpenId { get; set; }

    public AppUser AppUser { get; set; }
}

http://weblogs.asp.net/manavi/archive/2011/05/01/associations-in-ef-4-1-code-first-part-5-one-to-one-foreign-key-associations.aspx

I didn’t use virtual and you shouldn’t either.*

B) Declare an inheritance hierarchy with both table names explicitly stated, resulting in Table-Per-Type and a shared Primary Key.

using System.ComponentModel.DataAnnotations;

[Table("AppUser")]
public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

[Table("AdminUser")]      
public class AdminUser : AppUser
{
    public bool SuperAdmin { get; set; }
}

You’ll get 2 tables: One for AppUser, one for AdminUser. AdminUser is 1:1 with AppUser and is Dependent – meaning you can delete an AdminUser, but if you delete an AppUser when an AdminUser is still pointing at it, you’ll get a Constraint Violation Error.

C) There are 2 half-way methods of doing one-to-one in EF:

Entity-Splitting, where you have a single Class, but it’s stored in a primary table, and 1 or more one-to-one related tables.

Table-Splitting, where a tree of objects flattens out into a single table. For example a class with an Address property would have columns for the Address object, like Address_City, flattened into a single table.

*You can include virtual on any EF Property or Collections if you want to lazy-load them. This can result in infinite loops or loading the entire DB if you pass an object with lazy-loaded properties to, for example, the MVC JSON converter or anything else that walks the object hierarchy. The Lazy-Loading is always done Synchronously, blocking the thread, and without any notice. To summarize, the list of ways you can freeze your code, app or server with it is long. Avoid using virtual on EF classes. Yes there are a lot of code samples on the internet that use it. No, you still should not use it.

Leave a Comment