EF5 one-to-one without navigation

2019-03-05 03:33发布

问题:

I'm trying to do a one-to-one relationship, with the navigation property just on one side (MVC4, EF5, code first).

public class User {

  public int UserId { get; set; } //PK

  public int RankId { get; set; } //FK

  public virtual Rank { get; set; } //Navigation

}

public class Rank {

  public int RankId { get; set; }

}

Configuration:

 public class RankConfiguration : EntityTypeConfiguration<Rank>
{
    public RankConfiguration()
    {
      HasKey(e => e.RankId);
      Property(e => e.RankId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration ()
    {
      // PK
      HasKey(e => e.UserId);

      Property(e => e.RankId)
        .IsRequired();

      HasRequired(e => e.Rank)
        .WithRequiredDependent()
        .WillCascadeOnDelete(true);
    }
}

For what I see (and for the little I know), db is correctly generated, but I get this error:

A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'UserId'.

In a first try, I was thinking to create a join table (ref. here EF5 Fluent API one-to-one without navigator), don't know if was a good idea but I wasn't able to do with fluent API.

I have no idea why and what is wrong .. any help? many thanks in advance

UPDATE

First try After @soadyp comment, I tried to configure a one-to-one with a join table

HasRequired(e => e.Rank)
    .WithRequiredDependent()
    .Map(m =>
    {
      m.ToTable("UserRank");
      m.MapKey("RankId");
    })
    .WillCascadeOnDelete(true);

but I get this error when I try to migrate:

The specified table 'UserRank' was not found in the model. 
Ensure that the table name has been correctly specified.

Second try Probably I'm making a simple job too complicated, after reading this http://weblogs.asp.net/manavi/archive/2011/04/14/associations-in-ef-4-1-code-first-part-3-shared-primary-key-associations.aspx I just changed in this way

  HasRequired(e => e.Rank)
    .WithOptional()
    .WillCascadeOnDelete(true);

Everything is fine, BUT the UserId PK wasn't setted as Identity (with obvious problmes when I insert a row). If I specify it as Identity:

  Property(e => e.UserId)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

I get the following error:

Cascading foreign key 'FK_dbo.Users_dbo.Ranks_UserId' cannot be created where 
the referencing column 'Users.UserID' is an identity column.
Could not create constraint. See previous errors.

回答1:

OK, so i have copied your code and tried it and my answer has multiple parts:

  1. With your current configuration the generated database is messed up some how, see in the Users table the "UserId" is becoming the FK (i don't know why really) so "RankId" is just becoming a normal integer property (it is not a key), so i think this is what triggers the first exception you mentioned about the ReferentialConstraint, because if you think about it, the database knows that "UserId" is a primary key, and at the same time it is a foreign key but the actual key that is referenced by "UserId" which is "RankId" is not database generated so how is the database suppose to figure out all of this information.
  2. Now there might be a "right configuration to fix this but i couldn't find, so to solve this i removed the fluent configurations and Entity Framework created everything by convention and it did a great job (it figured out that "RankId" in the User class is actually a foreign key).

An advice, try to see what's wrong with the configuration and with every change you make use SQL Server Management Studio or any other tool you have to check out the generated database schema to be sure it is what you wish it to be, plus if you don't need the configuration just don't use it.



回答2:

1:1 code first in EF requires the dependent table to have the SAME primary key. Otherwise what you want to do will work.

EDIT Similar SO post Code First and Fluent API one to one relationship

Here is the MS EF site sample. http://msdn.microsoft.com/en-us/data/jj591620#RequiredToRequired