【问题标题】:EF Code First Many-to-Many with Additional Foreign KeyEF 代码优先多对多与附加外键
【发布时间】:2015-03-02 21:36:28
【问题描述】:

我正在使用 Entity Framework Code First 创建一个数据库,其中包含两个这样的实体:

public class Tenant {

    public Tenant() {
        Users = new HashSet<User>();
    }

    [Key]
    public int ID { get; set; }

    [Required]
    [StringLength(12)]
    public string Code { get; set; }

    [Required]
    [StringLength(200)]
    public string Description { get; set; }

    public virtual ICollection<User> Users { get; set; }

}

public class User {

    public User() {
        Tenants = new HashSet<Tenant>();
    }

    [Key]
    public Guid ID { get; set; }

    public virtual ICollection<Tenant> Tenants { get; set; }

}

您可以看到我有一个从租户到用户的导航属性,以及一个从用户到租户的导航属性。这正确地创建了多对多关系,并导致以下数据库结构:

CREATE TABLE Tenants (
    ID          INT NOT NULL,
    Code        NVARCHAR(12) NOT NULL,
    Description NVARCHAR(200) NOT NULL
)

CREATE TABLE Users (
    ID          UNIQUEIDENTIFIER NOT NULL
)

它创建了一个多对多链接表:

CREATE TABLE UserTenants (
    User_ID     UNIQUEIDENTIFIER NOT NULL,
    Tenant_ID   INT NOT NULL
)

我的问题是当我尝试向用户实体添加额外的外键字段和导航属性时:

public int CurrentTenantID { get; set; }
public virtual Tenant CurrentTenant { get; set; }

我希望这只是在 users 表中添加一个额外的字段:

CurrentTenantID INT NOT NULL

但是当我为这个新的外键生成迁移时,它做了一些疯狂的事情:

public override void Up()
{
    DropForeignKey("acc.UserTenants", "User_ID", "acc.Users");
    DropForeignKey("acc.UserTenants", "Tenant_ID", "acc.Tenants");
    DropIndex("acc.UserTenants", new[] { "User_ID" });
    DropIndex("acc.UserTenants", new[] { "Tenant_ID" });
    AddColumn("acc.Tenants", "User_ID", c => c.Guid());
    AddColumn("acc.Users", "CurrentTenantID", c => c.Int(nullable: false));
    AddColumn("acc.Users", "Tenant_ID", c => c.Int());
    CreateIndex("acc.Tenants", "User_ID");
    CreateIndex("acc.Users", "CurrentTenantID");
    CreateIndex("acc.Users", "Tenant_ID");
    AddForeignKey("acc.Users", "CurrentTenantID", "acc.Tenants", "ID", cascadeDelete: true);
    AddForeignKey("acc.Tenants", "User_ID", "acc.Users", "ID");
    AddForeignKey("acc.Users", "Tenant_ID", "acc.Tenants", "ID");
    DropTable("acc.UserTenants");
}

为什么要删除 UserTenants 表?它所要做的就是将新列添加到 users 表中,并创建一个外键约束!

【问题讨论】:

    标签: c# entity-framework database-migration


    【解决方案1】:

    我相信,这是因为 EF 现在需要您提示您要创建哪些关系。 尝试在您的 DbContext 中指定它(覆盖 OnModelCreating):

     protected override void OnModelCreating(DbModelBuilder modelBuilder)
     {
         base.OnModelCreating(modelBuilder);
    
         modelBuilder.Entity<User>().HasMany(b => b.Tenants).WithMany(c => c.Users);
         modelBuilder.Entity<User>().HasOptional(b => b.CurrentTenant);
     }
    

    【讨论】:

    • 我可以使用 DataAnnotation Attributes 指定这个吗?
    • 我不认为你可以做到多对多,有一个使用连接表的建议:stackoverflow.com/questions/18648600/…
    • 好的,谢谢。我想避免这样做,因为我真的不知道如何以这种方式进行迁移,因为它现在将数据库创建逻辑放在迁移配置类之外。
    • 嗨@BG100,迁移不应受到您通过 Fluent Api 而不是属性定义 FK 的事实的影响。你为什么相信他们是?
    • 啊等一下……它刚刚被点击了!我刚刚意识到,流畅的 API 命令实际上并没有对数据库结构进行更改,而只是描述了实体之间的关系,因此当我进行迁移时,它会根据 OnModelCreating 中给出的提示正确地进行... . 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多