EF无法识别关系密钥

时间:2013-11-15 10:12:16

标签: c# entity-framework ef-code-first ef-migrations

在我的EF6 Code First模型中,我有以下类:

class User : IdentityUser // so it has public string Id!
{
    public virtual long ItemId { get; set; }
    public virtual Item Item { get; set; }
}

class Item
{
    public virtual long Id { get; set;
    public virtual string UserId { get; set; }
    public virtual User User { get; set; }
}

在我的上下文中,我执行以下操作:

OnModelCreating(DbModelBuilder mB)
{
    mB.Entity<User>().HasOptional(x => x.Item).WithOptionalPrincipal(x => x.User).WillCascadeOnDelete(false);
}

但是,我的移植产生了以下内容:

CreateTable(
            "dbo.Items",
            c => new
                {
                    Id = c.Long(nullable: false, identity: true),
                    UserId = c.String(),
                    User_Id = c.String(maxLength: 128),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Users", t => t.User_Id)
            .Index(t => t.User_Id);

我忘了做什么?

更新:我还尝试将[ForeignKey("User")]添加到Item.UserId

UPDATE2: 我发现了一种解决方法,但它不是很漂亮......

OnModelCreating(DbModelBuilder mB)
{
    mB.Entity<User>().HasOptional(x => x.Item).WithMany().HasForeignKey(x => x.ItemId);
    mB.Entity<Item>().HasOptional(x => x.User).WithMany().HasForeignKey(x => x.UserId);
}

1 个答案:

答案 0 :(得分:0)

据我了解,Entity Framework通过使2个实体共享相同的主键来实施一对一的关系。这意味着不需要单独的外键列,因为主键属性也充当外键。

因此,删除多余的外键并将Item的键的类型更改为string,以便它可以引用用户的ID:

class User : IdentityUser // so it has public string Id!
{
    public virtual Item Item { get; set; }
}

class Item
{
    public string Id { get; set;}
    public virtual User User { get; set; }
}

现在,当关系的两端都是必需的或双方都是可选的时,实体框架无法识别依赖关系和主体。依赖项是获取引用主体密钥的外键的依赖项。

所以试试这个:

modelBuilder.Entity<User>()
            .HasOptional(f => f.Item). //Item is dependent and 
                                       //gets the foreign key
            .WithOptionalPrincipal(s => s.User);

<强>限制性条款

我没有试过这个或做过这个,我没有得到的是这个。 如果两端都是可选的,那么Item如何拥有一个也是主键的User的外键?主键是必需的,但可选的外键不是。所以他们不可能是同一个。

因此,如果EF现在添加了一个可选的外键,我会为它添加一个唯一的索引以确保它是1到1.因为它可以为空,所以你需要在迁移中使用sql来实现它

Sql("CREATE INDEX ON Item(User_Id) UNIQUE WHERE User_Id IS NOT NULL")

参考文献:

http://msdn.microsoft.com/en-us/data/jj713564

http://msdn.microsoft.com/en-us/data/jj591620.aspx

它在该页面上说:

  

当关系的两端都是可选的时,请使用   HasOptional之后的WithOptionalPrincipal或WithOptionalDependent   方法

Do I define a relationship between two entities on the dependent or the principal?