实体框架,代码优先:将主 - 细节与零到一关系相结合 [英] Entity Framework, code-first: combining master-detail with zero-to-one relationship
问题描述
我有一个简单的主 - 细节关系使用代码第一EF:
public class User
{
public string Id {get;组; }
public ICollection< Tasks>任务{get;组;
}
public class Task
{
public string Id {get;组;
[必需]
public string UserId {get;组; }
public User User {get;组; }
}
现在我要修改它,以便用户可以拥有一个,最多重要任务。所以我修改User类来添加它:
public class User
{
public string Id {得到;组; }
public ICollection< Tasks>任务{get;组; }
public string MostImportantTaskId {get;组; }
[ForeignKey(MostImportantTaskId)]
public Task MostImportantTask {get;组;
}
当我运行添加迁移
,但是,我得到了一个意想不到的结果。 EF尝试向 Tasks
表中添加一个 User_Id
列,我不想要,并删除外部关键我需要主/细节关系:
public override void Up()
/ pre>
{
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()
{
// ...
}
那么如何维护用户和任务之间的主要细节关系,同时将一个任务的引用添加到
User
class?
解决方案这不是我过于熟悉的东西,但我相信你正在寻找是
InverseProperty
。由于您的用户
类与Task
有多个关系,您需要添加InverseProperty
到您的任务
集合,将其指向用户
属性任务
。
所以如果您在
用户
类[InverseProperty(User)]
public ICollection< Task>任务{get;组;
然后当您运行迁移时,将生成以下代码,这些代码看起来是您的之后
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的错字。
I have a simple master-detail relationship using code first 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; } }
Now I want to modify it so that users can have a single, most important task. So I modify the User class to add it:
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; } }
When I run
Add-Migration
, however, I get an unexpected result. EF is trying to add aUser_Id
column to theTasks
table, which I don't want, and dropping the foreign key I need for the master/detail relationship: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() { // ... }
So how do I maintain the master detail relationship between users and tasks, while adding a reference to a single task to the
User
class?解决方案It's not something I'm overly familiar with but I believe what you're looking for is
InverseProperty
. As yourUser
class has multiple relationships withTask
, you need to add theInverseProperty
to yourTasks
collection to point it to theUser
property onTask
.So if you make this change in your
User
class[InverseProperty("User")] public ICollection<Task> Tasks { get; set; }
then when you run a migration the following code gets generated, which looks to be what you're after
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"); }
Based on an example at entityframeworktutorial.net.
Note: I've assumed where you've referenced a
Tasks
class in your code it was a typo forTask.
这篇关于实体框架,代码优先:将主 - 细节与零到一关系相结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!