简体   繁体   English

Code First EF5:One-to-Zero-One关系不起作用

[英]Code First EF5: One-to-Zero-or-One relationship is not working

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. 我正在使用Entity Framework 5,MVC 4,.NET 4.5作为我的Web应用程序,使用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: 使用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 ie 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. EF Powertools edmx视图中的关系看起来很好,但是我无法使用Foreign键来使用UserProfile UserId。

Is my Fluent API wrong or is it my models? 我的Fluent API是错误的还是我的模特? Please help - I am truly stuck! 请帮忙 - 我真的被卡住了!

Your mapping with Fluent API is OK, but remove the UserProfile.JoggerId and the Jogger.UserId properties from your model and it should work. 使用Fluent API进行映射是可以的,但是从模型中删除UserProfile.JoggerIdJogger.UserId属性应该可以正常工作。 The reason is that Entity Framework uses the primary key of Jogger as the foreign key to UserProfile , so you don't need to (and can't) have a separate foreign key property. 原因是Entity Framework使用Jogger的主键作为UserProfile的外键,因此您不需要(也不能)具有单独的外键属性。 This kind of one-to-one relationship is called " Shared Primary Key Association ". 这种一对一的关系称为“ 共享主键关联 ”。

Edit 编辑

Keep in mind that the primary key of Jogger (as the dependent of the relationship) is not autogenerated in the database, only the primary key of UserProfile is autogenerated (as the principal of the relationship). 请记住, Jogger的主键(作为关系的依赖) 不是在数据库中自动生成的,只有UserProfile的主键是自动生成的(作为关系的主体)。

The way how you would insert a UserProfile or a Jogger or both into the database is the following: UserProfileJogger或两者插入数据库的方式如下:

  • If you want to insert a UserProfile without a Jogger just add it to the context: 如果要在没有Jogger的情况下插入UserProfile ,只需将其添加到上下文中:

     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(); } 
  • If you want to insert a UserProfile with a Jogger in a single step: 如果要在一个步骤中插入带有JoggerUserProfile

     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(); } 
  • If you want to insert a Jogger (and it must be a Jogger for an existing UserProfile ): 如果要插入Jogger (它必须是现有UserProfileJogger ):

     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(); } 

Edit 2 编辑2

For your use case where you don't have the UserId directly available but the Name (as authenticated user) instead you must load the key or the UserProfile first from the database: 对于您没有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();
    }
}

Or loading the UserProfile will work as well: 或者加载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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM