实体框架,代码优先:将主细节与零对一关系结合在一起

我有一个使用代码优先EF的简单的主从关系:

public class User
{
     public string Id { get; set; }
     public ICollection<Tasks> Tasks { get; set; }
}

public class Task
{
    public string Id { get; set; }

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

现在,我想对其进行修改,以便用户可以执行一项最重要的任务.所以我修改了User类来添加它:

public class User
{
     public string Id { get; set; }
     public ICollection<Tasks> Tasks { get; set; }
     public string MostImportantTaskId { get; set; }

     [ForeignKey("MostImportantTaskId")]
     public Task MostImportantTask { get; set; }
}

但是,当我运行Add-Migration时,会得到意外结果. EF尝试将我不想要的User_Id列添加到Tasks表中,并删除主/明细关系所需的外键:

public override void Up()
{
    DropForeignKey("dbo.Tasks", "UserId", "dbo.Users");
    AddColumn("dbo.Tasks", "User_Id", c => c.String(maxLength: 128));
    AddColumn("dbo.Users", "MostImportantTaskId", c => c.String(maxLength: 128));
    CreateIndex("dbo.Tasks", "User_Id");
    CreateIndex("dbo.Users", "MostImportantTaskId");
    AddForeignKey("dbo.Users", "MostImportantTaskId", "dbo.Tasks", "Id");
    AddForeignKey("dbo.Tasks", "User_Id", "dbo.Users", "Id");
}

public override void Down()
{
    // ...
}

那么,如何在向用户类添加对单个任务的引用的同时,维护用户与任务之间的主从关系?

最佳答案
这不是我太熟悉的东西,但是我相信您正在寻找的是InverseProperty.由于您的User类与Task具有多个关系,因此您需要将InverseProperty添加到Tasks集合中,以将其指向Task上的User属性.

因此,如果您在User类中进行此更改

[InverseProperty("User")]
public ICollection<Task> Tasks { get; set; }

然后,当您运行迁移时,将生成以下代码,看起来就像您所追求的

public override void Up()
{
    AddColumn("dbo.Users", "MostImportantTaskId", c => c.String(maxLength: 128));
    CreateIndex("dbo.Users", "MostImportantTaskId");
    AddForeignKey("dbo.Users", "MostImportantTaskId", "dbo.Tasks", "Id");
}

public override void Down()
{
    DropForeignKey("dbo.Users", "MostImportantTaskId", "dbo.Tasks");
    DropIndex("dbo.Users", new[] { "MostImportantTaskId" });
    DropColumn("dbo.Users", "MostImportantTaskId");
}

基于entityframeworktutorial.net处的示例.

注意:我假设您在代码中引用Tasks类的地方是Task的错字.

转载注明原文:实体框架,代码优先:将主细节与零对一关系结合在一起 - 代码日志