views:

199

answers:

2

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

I found this question http://stackoverflow.com/questions/2089395/one-to-one-relationships-in-entity-framework-4-v2-with-poco, but the article that the answer references was not useful (there is one line of code that is a 1-1 relationship, but no mention of how to define it).

+1  A: 

Are you just looking for something like this?

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Profile Profile { get; set; }
    public int ProfileId { get; set; }
}

public class Profile
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
    // etc...
}

public class UserMapping : EntityConfiguration<User>
{
    public UserMapping()
    {
        this.HasKey(u => u.Id);
        this.Property(u => u.Username).HasMaxLength(32);

        // User has ONE profile.
        this.HasRequired(u => u.Profile);
    }
}

public class ProfileMapping : EntityConfiguration<Profile>
{
    public ProfileMapping()
    {
        this.HasKey(p => p.Id);
        this.Property(p => p.FirstName).HasMaxLength(32);
        this.Property(p => p.LastName).HasMaxLength(32);
        this.Property(p => p.PostalCode).HasMaxLength(6);
    }
}

EDIT: Yeah I didn't have VS in front of me but you need to add the following line in the UserMapping instead of the current HasRequired and also add a ProfileId property (instead of Profile_Id that you added):

this.HasRequired(u => u.Profile).HasConstraint((u, p) => u.ProfileId == p.Id);

I currently don't think there's a way around this, but I'm sure it'll change since we're only in CTP4. It'd be nice if I could say:

this.HasRequired(u => u.Profile).WithSingle().Map(new StoreForeignKeyName("ProfileId"));

This way I wouldn't have to include a ProfileId property. Maybe there is a way around this currently and it's still to early in the morning for me to think :).

Also remember to call .Include("Profile") if you want to include a "navigational property".

TheCloudlessSky
Does this work for you? I cannot get it to work.I am not generating the database automatically as I have existing tables. My profile table has Id as PK and FK (as the relationship is 1:1). I take it that this is the same as you. If I try and run your code, I get an error:Invalid column name 'Profile_Id'.If I add that column to User (not that I want it there), user is returned but profile is null. The sql generated is :SELECT [Extent1].[Id] AS [Id], [Extent1].[Username] AS [Username], [Extent1].[Profile_Id] AS [Profile_Id]FROM [dbo].[Users] AS [Extent1]Any ideas?
zaph0d
hmm. On second inspection, looks like this works fine on sqlce4, but not sql server 2010 unless I am missing something.
zaph0d
@zaph0d - If you want to access a property that is "another entity", you need to "include" it. The way to do that would be `context.Users.Include("Profile")`. Profile is a "navigation property" that will require a JOIN in SQL. I've edited my post with the extra bit of info I forgot for profile.
TheCloudlessSky
@zaph0d - I was going to suggest you post this on the MSDN forums as well to see if there is a better way, but I see you already did :). Perhaps you should link back to this SO post too.
TheCloudlessSky
A: 
public class User

{

public int Id { get; set; } 
public string Username { get; set; } 

public virtual Profile Profile { get; set; } 

}

public class Profile {

public int Id { get; set; } 

public int UserID { get; set; } 

public string FirstName { get; set; } 
public string LastName { get; set; } 
public string PostalCode { get; set; } 

}

Add the virtual Profile and the UserID and I think that should get you there.

Terrence