实体框架创建外键对象,而不是使用已经可用的对象

bit*_*ler 30 ef-code-first entity-framework-4.1

我当前的项目基于Entity Framwork代码优先.我有三种类型:Task,TaskType和Module.

    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; }
    }
Run Code Online (Sandbox Code Playgroud)

在表内为Task-type定义了外键关系.

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

        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);
Run Code Online (Sandbox Code Playgroud)

这会在我的TaskType表和我的Modules-table中创建一个新行,而不是仅使用已经可用的TaskType-ID和Module-ID.

我希望我明白我的问题是什么;-)

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

问候,凯文

Lad*_*nka 60

如果不使用相同的上下文实例来加载相关实体,则不能简单地将它们添加到新实体中,并期望使用数据库中的现有记录.新上下文不知道数据库中存在这些实例 - 您必须将其说明为上下文.

解决方案:

  1. 对加载相关实体和保存新实体使用相同的上下文
  2. 不要加载相关实体并使用虚拟对象
  3. 从第一个上下文加载实体并将它们分离,将实体附加到新上下文,然后将它们分配给新实体.
  4. 添加一个新的实体关系后手动更改关系的状态AddedUnchanged

示例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);
Run Code Online (Sandbox Code Playgroud)

示例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);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

  • 哇,这是一些很棒的答案:-)非常感谢.我想我会拿#3 ...... (2认同)

Eti*_*nne 6

我是实体框架的新手,但我遇到了同样的问题,我的外键属性已填充,但导航对象为null,代码如下:

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;}
Run Code Online (Sandbox Code Playgroud)

}

将navigation属性设置为virtual可修复问题并启用延迟加载:

    [ForeignKey("EntryRecordId")]
    public virtual EntryRecord EntryRecord { get; set;}
Run Code Online (Sandbox Code Playgroud)