1

None of the similair questions seem to be able to solve this problem. I'm using Entity Framework 5, MVC 4, .NET 4.5 for my web app, designed with VS 2012.

I have 2 classes that are supposed to be in a parent-child relationship.

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    // Other stuff

    public int? JoggerId { get; set; }
    public virtual Jogger Jogger{ get; set; }
}

and

 public class Jogger
{
    [Key]
    public int JoggerId { get; set; }

    [Required, ForeignKey("UserId")]
    public int UserId { get; set; }
    public virtual UserProfile UserProfile { get; set; }
}

With Fluent API:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<UserProfile>()
            .HasOptional(x => x.Jogger)
            .WithRequired(c => c.UserProfile)
            .WillCascadeOnDelete(true);

        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);
    }

A User can be a Jogger but can also not be a Jogger i.e. one User to zero or one Jogger. the relationship looks fine on the EF Powertools edmx view but I cannot get the Foreign key to work with the UserProfile UserId.

Is my Fluent API wrong or is it my models? Please help - I am truly stuck!

4

1 回答 1

3

您与 Fluent API 的映射是可以的,但是从您的模型中删除UserProfile.JoggerIdJogger.UserId属性,它应该可以工作。原因是实体框架使用主键Jogger作为外键UserProfile,所以你不需要(也不能)有一个单独的外键属性。这种一对一的关系称为“共享主键关联”。

编辑

请记住,Jogger(作为关系的依赖项)的主键不是在数据库中自动生成的,只有 的主键UserProfile是自动生成的(作为关系的主体)。

您如何将 aUserProfile或 aJogger或两者插入数据库的方式如下:

  • 如果要插入UserProfile不带 a 的Jogger,只需将其添加到上下文中:

    using (var context = new MyContext())
    {
        var newUserProfile = new UserProfile();
        // no key needs to be supplied, the DB will take care
    
        context.UserProfiles.Add(newUserProfile);
        context.SaveChanges();
    }
    
  • 如果你想在一个步骤中插入UserProfilea :Jogger

    using (var context = new MyContext())
    {
        var newUserProfile = new UserProfile { Jogger = new Jogger() };
        // no key needs to be supplied, neither for UserProfile
        // nor for Jogger, the DB will take care
    
        context.UserProfiles.Add(newUserProfile);
        context.SaveChanges();
    }
    
  • 如果要插入 a Jogger(并且它必须是Jogger现有的a UserProfile):

    using (var context = new MyContext())
    {
        var newJogger = new Jogger { JoggerId = someExistingUserProfileId };
        // a valid key needs to be supplied, otherwise you would violate a FK
        // constraint in the database
    
        context.Joggers.Add(newJogger);
        context.SaveChanges();
    }
    

编辑 2

对于您没有UserId直接可用但Name(作为经过身份验证的用户)的用例,您必须从数据库加载密钥或第UserProfile一个:

// we are in an ASP.NET MVC controller action here
using (var context = new MyContext())
{
    string userName = User.Identity.Name;
    int? userId = context.UserProfiles
        .Where(u => u.Name == userName)
        .Select(u => (int?)u.UserId)
        .SingleOrDefault();

    if (userId.HasValue)
    {
        var newJogger = new Jogger { JoggerId = userId.Value };
        context.Joggers.Add(newJogger);
        context.SaveChanges();
    }
}

或者加载UserProfile也可以:

using (var context = new MyContext())
{
    string userName = User.Identity.Name;
    UserProfile userProfile = context.UserProfiles
        .Where(u => u.Name == userName)
        .SingleOrDefault();

    if (userProfile != null)
    {
        userProfile.Jogger = new Jogger();
        // I believe you don't need to set the JoggerId key now,
        // I'm not sure though

        context.SaveChanges();
        // Change tracking recognizes the new Jogger
        // no context.Joggers.Add is required
    }
}
于 2013-07-31T00:08:02.567 回答