实体框架创建外键对象,而不是使用已经可用的对象 [英] Entity Framework creates foreign key objects instead of using those that are already available

查看:91
本文介绍了实体框架创建外键对象,而不是使用已经可用的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前的项目是基于实体框架代码。我有三种类型:任务,TaskType和Module。

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

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

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

为表格类型定义了外键关系。我的问题是,当我尝试创建一个链接到已经可用的TaskType和Module对象(ID = 1)的新任务对象时,这些对象被创建为新行在其相应的表格中。

  TaskRepository repo = new TaskRepository(); 

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

Tasks.Add(task);

这将在我的TaskType表和我的Modules-table中创建一个新行,而不是使用已经提供的TaskType-ID和Module-ID。



我希望我明确说明我的问题; - )



提前感谢您的帮助。我很感激。



Regards,
Kevin

解决方案

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



解决方案:


  1. 对于加载相关实体并保存新实体,使用相同的上下文

  2. 不加载相关实体并使用虚拟对象

  3. 从第一个上下文加载实体并将其分离,将实体附加到新的上下文,然后将它们分配给新实体。

  4. 添加新实体后与关系手动将关系状态从添加不变

1的示例:

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

任务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 = 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 = 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 = new Task();
task.Module = module;
task.Type = taskType;

context.Tasks.Add(task);

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


my current project is based on Entity Framwork code-first. I have three types: Task, TaskType and 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; }
    }

There are foreign key relations defined inside the table for the Task-type.

My problem is that when I try to create a new Task-object linked to already available TaskType and Module objects (ID = 1), those objects are created as new rows in their corresponding tables.

        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);

This creates a new row in my TaskType-table and in my Modules-table as well instead of just using the already available TaskType-ID and Module-ID.

I hope I made clear what my problem is ;-)

Thanks in advance for your help. I appreciate it.

Regards, Kevin

解决方案

If you don't use the same context instance to load related entities you cannot simply add them to the new entity and expect that existing records in the database will be used. The new context doesn't know that these instances exist in the database - you must to say it to the context.

Solutions:

  1. Use the same context for both loading related entities and saving new entity
  2. Don't load related entities and use dummy objects
  3. Load entities from the first context and detach them, attach entities to a new context and after that assign them to a new entity.
  4. After adding a new entity with relations manually change state of relations from Added to Unchanged

Example for 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);

Example for 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);

Example for 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);

Example for 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;

这篇关于实体框架创建外键对象,而不是使用已经可用的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆