2011-06-06 46 views
28

我的当前项目基于实体框架代码优先。我有三种类型:任务,任务类型和模块。实体框架创建外键对象而不是使用已有的外键对象

public class Task 
    { 
     public int ID { get; set; } 
     public Module Module { get; set; } 
     public TaskType Type { get; set; } 
    } 

    public class TaskType 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
    } 

    public class Module 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
    } 

表中为任务类型定义了外键关系。

我的问题是,当我尝试创建一个新的Task-object链接到已经可用的TaskType和Module对象(ID = 1)时,这些对象在其相应的表中创建为新行。

 TaskRepository repo = new TaskRepository(); 

     Task task = new Task(); 
     task.Module = Modules.SingleOrDefault(m => m.ID == 1); 
     task.Type = TaskTypes.SingleOrDefault(t => t.ID == 1); 

     Tasks.Add(task); 

这会在我的任务类型表,在我的模块表新行以及而不只是使用已有的任务类型-ID和模块ID的。

我希望我清楚我的问题是什么;-)

在此先感谢您的帮助。我很感激。

问候, 凯文

+1

您是否使用相同的上下文实例来加载'Module'和'TaskType'并保存'Task'? – 2011-06-06 09:43:44

+0

不,我使用另一个类中的helper方法接收Module和TaskType,该方法再次保存了我的DbContext实例。 – bitfrickler 2011-06-06 10:22:31

回答

58

如果不使用相同的上下文实例加载相关实体,你不能简单地将它们添加到新的实体,并预计,在数据库中已有的记录将被使用。新的上下文不知道这些实例存在于数据库中 - 您必须对上下文进行说明。

解决方案:

  1. 使用相同的上下文两个装载相关实体和保存新的实体
  2. 不要加载相关实体和使用虚拟对象从第一方面
  3. 负荷实体和其分离,将实体附加到新的上下文,然后将它们分配给新的实体。
  4. 添加新实体关系手动从Added改变关系的状态,以Unchanged

实施例1后:

var module = context.Modules.SingleOrDefault(m => m.ID == 1); 
var taskType = context.TaskTypes.SingleOrDefault(t => t.ID == 1); 

Task task = new Task(); 
task.Module = module; 
task.Type = taskType; 

context.Tasks.Add(task); 

实施例2:

var module = new Module { Id = 1 }; 
var taskType = new TaskType { Id = 1 }; 

context.Modules.Attach(module); 
context.TaskTypes.Attach(taskType); 

Task task = new Task(); 
task.Module = module; 
task.Type = taskType; 

context.Tasks.Add(task); 

实施例3 :

var module = otherContext.Modules.SingleOrDefault(m => m.ID == 1); 
otherContext.Entry(module).State = EntityState.Detached; 

var taskType = otherContext.TaskTypes.SingleOrDefault(t => t.ID == 1); 
otherContext.Entry(taskType).State = EntityState.Detached; 

context.Modules.Attach(module); 
context.TaskTypes.Attach(taskType); 

Task task = new Task(); 
task.Module = module; 
task.Type = taskType; 

context.Tasks.Add(task); 

例4:

var module = otherContext.Modules.SingleOrDefault(m => m.ID == 1); 
otherContext.Entry(module).State = EntityState.Detached; 

var taskType = otherContext.TaskTypes.SingleOrDefault(t => t.ID == 1); 
otherContext.Entry(taskType).State = EntityState.Detached; 

Task task = new Task(); 
task.Module = module; 
task.Type = taskType; 

context.Tasks.Add(task); 

context.Entry(module).State = EntityState.Unchanged; 
context.Entry(taskType).State = EntityState.Unchanged; 
+2

哇,这是一些很棒的答案:-)非常感谢。我想我会采取#3 ... – bitfrickler 2011-06-06 11:07:10

+0

需要使用相同的上下文,也是同一个上下文的同一个实例。这很重要。 – 2016-02-27 11:36:02

5

我是新来的实体框架,但我只是碰到了同样的问题,在这里居住了我的外键属性,但导航对象为空,下面类似的代码:

public class EntryRecord 
{   
    [Key] 
    public int Id { get; set; } 
} 
public class QueueItem 
{  
    [Key] 
    public int Id { get; set; } 


    public int EntryRecordId { get; set; } 

    [ForeignKey("EntryRecordId")] 
    public EntryRecord EntryRecord { get; set;} 

}

导航属性设置为虚拟修复的问题,并且使得延迟加载:

[ForeignKey("EntryRecordId")] 
    public virtual EntryRecord EntryRecord { get; set;}