为什么EF会生成外键?

时间:2015-12-20 15:24:40

标签: c# entity-framework

我需要一对一(可选)。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<PinnacleAccount>().HasKey(x => x.Id);

    modelBuilder.Entity<PinnacleAccount>()
        .HasRequired(x => x.User)
        .WithOptional(x => x.PinnacleAccount);

    base.OnModelCreating(modelBuilder);
}

当我运行&#39; Add-Migration Init&#39;我检查生成的迁移并查看:

CreateTable(
                "dbo.PinnacleAccounts",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        ClientId = c.String(),
                        Password = c.String(),
                        PercentForBet = c.Int(nullable: false),
                        UserId = c.String(),
                        User_Id = c.String(nullable: false, maxLength: 128),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.AspNetUsers", t => t.User_Id)
                .Index(t => t.User_Id);

但我有属性UserId。为什么ef创建User_Id

   public class ApplicationUser : IdentityUser
    {
        public virtual PinnacleAccount PinnacleAccount { get; set; }
        public int? PinnacleAccountId { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }

3 个答案:

答案 0 :(得分:4)

当您在实体框架中建立1:0.1的关系时,第一个实体的主键必须与第二个实体的主键相同。您无法指定哪个属性是FK,因为它不是必需的。我会解释一下:

如果User只有一个PinnacleAccount,则为1:0.1关系。因此,每个PinnacleAccount都属于User。这意味着,PinnacleAccount是一个弱实体,因此,它的主键也是一个User外键。

PinnacleAccount不应该有自己的ID,只有UserId。所以,PinnacleAccount应该是这样的:

public class PinnacleAccount
{
    public string UserId { get; set; } //PK AND FK
    public string ClientId  { get; set; }
    public string Password { get; set; }
    public string PercentForBet { get; set; }
}

映射:

modelBuilder.Entity<PinnacleAccount>().HasKey(x => x.UserId);
modelBuilder.Entity<User>()
    .HasOptional(i => i.PinnacleAccount)
    .WithRequired(x => x.User);

这是建立1:0.1关系的唯一方法。

希望它有所帮助!

答案 1 :(得分:2)

也许您需要在模型中声明映射关系

this.HasOptional(t => t.User)
                .WithMany(t => t.PinnacleAccount)
                .HasForeignKey(d => d.UserId);

答案 2 :(得分:0)

@Fabio Luz给出了正确的答案,但对于已经设置错误且需要纠正错误的任何人,请按照以下方式进行操作。

我的&#39; PinnacleAccount&#39;看起来如下(我使用GUID,但你明白了):

.parent

我可以从PinnacleAccount访问用户,但不是相反,我想纠正。为此,我必须创建两个迁移。

首先,我将UserId属性编辑为UserIdOld并创建了类似的迁移:

$('.mobile-select-supplier a').click(function() {
    $(this).closest('.parent').find('.extra-suppliers.mobile.only').show();
});

这允许我释放UserId列名,并使用UserId填充User_Id列(因为这是alter语句)。

然后我将课程改为:

public class PinnacleAccount
{
  [Required]
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public Guid Id { get; set; }

  public virtual ApplicationUser User { get; set;  }
  [Required]
  public virtual string UserId { get; set; }  
}

随后对@Fabio Luz描述的映射进行了更改。

然后我创建了第二个迁移,看起来像:

public override void Up()
{
    DropForeignKey("dbo.PinnacleAccount", "UserId", "dbo.AspNetUsers");
    DropIndex("dbo.PinnacleAccount", new[] { "UserId" });
    RenameColumn(table: "dbo.PinnacleAccount", name: "UserId", newName: "User_Id");
    AddColumn("dbo.PinnacleAccount", "UserIdOld", c => c.String(nullable: false));
    AlterColumn("dbo.PinnacleAccount", "User_Id", c => c.String(maxLength: 128));
    CreateIndex("dbo.PinnacleAccount", "User_Id");
    AddForeignKey("dbo.PinnacleAccount", "User_Id", "dbo.AspNetUsers", "Id");
}

public override void Down()
{
    DropForeignKey("dbo.PinnacleAccount", "User_Id", "dbo.AspNetUsers");
    DropIndex("dbo.PinnacleAccount", new[] { "User_Id" });
    AlterColumn("dbo.PinnacleAccount", "User_Id", c => c.String(nullable: false, maxLength: 128));
    DropColumn("dbo.PinnacleAccount", "UserIdOld");
    RenameColumn(table: "dbo.PinnacleAccount", name: "User_Id", newName: "UserId");
    CreateIndex("dbo.PinnacleAccount", "UserId");
    AddForeignKey("dbo.PinnacleAccount", "UserId", "dbo.AspNetUsers", "Id", cascadeDelete: true);
}

这给了我正确的1:0.1。感谢Fabio展示如何正确创建一个!