Entity Framework создает объекты внешнего ключа вместо использования уже доступных - PullRequest
29 голосов
/ 06 июня 2011

Мой текущий проект основан на коде 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; }
    }

В таблице определены отношения внешних ключей для типа Task.

Моя проблема заключается в том, что при попытке создатьновый объект Task, связанный с уже доступными объектами 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);

Это создает новую строку в моей таблице TaskType.и в моей таблице модулей вместо того, чтобы просто использовать уже имеющиеся TaskType-ID и Module-ID.

Надеюсь, я ясно дал понять, в чем моя проблема; -)

Заранее спасибоза помощь.Я ценю это.

С уважением, Кевин

Ответы [ 2 ]

59 голосов
/ 06 июня 2011

Если вы не используете один и тот же экземпляр контекста для загрузки связанных сущностей, вы не можете просто добавить их в новую сущность и ожидать, что будут использоваться существующие записи в базе данных. Новый контекст не знает, что эти экземпляры существуют в базе данных - вы должны сказать это контексту.

Решения:

  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;
6 голосов
/ 15 мая 2012

Я новичок в платформе сущностей, но я столкнулся с той же проблемой, когда заполнено мое свойство внешнего ключа, но объект навигации был пустым, с кодом вроде:

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;}
...