Search code examples
c#entity-framework-4.1ef-code-firstentity-relationship

Do I need to use a property ClassId to represent a relationship in the Code First (Entity Framework)?


I am using the entity framework (code first).

I would like to know if I really need to use a property with Id for relationship with another entity as in the code below.

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

public class Profile
{
    public int Id { get; set; }
    public string Description{ get; set; }
}

For this way when I insert a user by setting the profileid property performs perfectly.

But when I don't use the profileid property in the Profile class,

public class User
{
    public int Id { get; set; }
    public string Login { get; set; }
    public string Password { get; set; }
    public Profile Profile{ get; set; }
}

public class Profile
{
    public int Id { get; set; }
    public string Description{ get; set; }
}

the execution the insert method adds another profile record. Why?

My mapping:

public class EntityMapping<Entity> : EntityTypeConfiguration<Entity> where Entity : EntityBase
{
    public EntityMapping()
    {
        HasKey(e => e.Id);
        Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

public class UserMapping : EntityMapping<User>
{
    public UserMapping() : base()
    {
         ToTable("USER");
         Property(p => p.Id).HasColumnName("USER_CD_USER");
         Property(p => p.Login).HasColumnName("USER_TX_LOGIN").HasMaxLength(10).IsRequired();
         Property(p => p.Password).HasColumnName("USUA_TX_PASSWORD").HasMaxLength(8).IsRequired();
         HasRequired(e => e.Profile).WithMany(p => p.Users).Map(p => p.MapKey("PROF_CD_PROFILE"));
     }
}

public class ProfilelMapping : EntityMapping<Profile>
{
    public ProfileMapping()
        : base()
    {
        ToTable("PROFILE");
        Property(p => p.Id).HasColumnName("PROF_CD_PROFILE");
        Property(p => p.Description).HasColumnName("PROFILE_DS_PROFILE").HasMaxLength(20).IsRequired();
        HasMany(e => e.Users).WithRequired(p => p.Profile);
    }
}

Solution

  • You are asking two questions.

    Do I need to use FK property?

    No you don't but EF behavior changes if you use it or not. More about it is in separate answer and linked blog article.

    Why EF inserts Profile again?

    Creating relations with existing entities requires special care. EF doesn't check if your entity exists in the database - you must tell it to EF. Here is one of many ways how to achieve that (without loading profile from the database):

    var user = GetNewUserSomewhere();
    context.Users.Add(user);
    
    // Dummy profile representing existing one.
    var profile = new Profile() { Id = 1 };
    // Informing context about existing profile.
    context.Profiles.Attach(profile);
    
    // Creating relation between new user and existing profile
    user.Profile = profile;
    
    context.SaveChanges();