Разрыв отношений POCO - PullRequest
       31

Разрыв отношений POCO

3 голосов
/ 07 февраля 2012

У меня проблема с разрывом отношений между двумя сущностями.Скажем, у нас есть Child сущность, которая принадлежит одному Parent, а Parent имеет много Child сущностей.Теперь в моем пользовательском интерфейсе пользователь может выбрать переключатель, чтобы выбрать Parent, которому принадлежит Child, или он может выбрать «Нет».Проблема в том, что когда я редактирую запись Child и выбираю «Нет», она, похоже, не нарушает существующие отношения.

В своей бизнес-логике я делаю следующее:

child.Parent = parentRepository.Find(command.ParentID);

Метод репозитория возвращает ноль, если ни одна запись не соответствует переданному идентификатору, а выбор «Нет» дает идентификатор 0, когда я отлаживаю и перехожу через эту строку, Child.Parent по-прежнему имеет ссылку наранее выбранный родительский объект.На самом деле, даже явно устанавливая Child.Parent = null;похоже, не нарушает связь.

Чтобы добавить к моему замешательству, это непоследовательное поведение.Время от времени один и тот же код делает разрыв отношения и устанавливает для Child.Parent значение null!Может кто-нибудь указать мне правильное направление?

ОБНОВЛЕНИЕ

Я обновил свой код, чтобы гарантировать, что репо возвращает ноль.

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
    child.parent = null;
else
    child.parent = parent;

Отладка показывает, что строка child.parent = null; выполняется , но когда я проверяю child.parent после этой строки, она все равно показывает ссылку на ранее указанный объект Parent.Но время от времени это правильно устанавливает в ноль.Эта версия работает:

Parent parent = parentRepository.Find(command.ParentID);
if (parent == null)
{
    child.parent = null;
    child.parent = null;
}
else
    child.parent = parent;

Почему я должен установить его в null дважды, чтобы получить согласованное поведение?Должен ли я явно объявить, что Parent может быть каким-либо образом обнуляемым на сущности Child?

1 Ответ

1 голос
/ 07 февраля 2012

Да, вам нужно объявить, что родительский элемент может иметь значение NULL.

Если вы предоставляете свойство внешнего ключа для дочернего элемента, оно должно иметь значение NULL.Поэтому, если у вашего ребенка есть свойство ParentId, оно должно выглядеть следующим образом:

public int? ParentId { get; set; }
public virtual Parent { get; set; }

Если вы используете свободный API, вы можете сказать EF, что родительский элемент обнуляется следующим образом:

modelBuilder.Entity<Child>.HasOptional(d => d.Parent).WithMany(p => p.Children);

Или вот так, если вы объявляете связь с основного конца, а не с зависимого конца:

modelBuilder.Entity<Parent>.HasMany(p => p.Children).WithOptional(d => d.Parent);

Странно, что child.Parent должен быть дважды установлен в null.Вы пытались войти в код, чтобы понять, почему?Вы также можете попробовать это для своего свойства Parent, чтобы точно увидеть, что происходит:

private Parent _parent;
public virtual Parent
{
    get { return _parent; }
    set { _parent = value; }
}

Это код, который вы можете использовать, чтобы убедиться, что для частного поля установлено значение null.

Ответ на комментарий

Звучит так, будто существует проблема с отложенной загрузкой.Попробуйте это.

В вашем методе поиска в хранилище, стремясь загрузить родителя.Вы можете сделать это примерно так:

context.Children.Include(c => c.Parent).Find(id);

Это сделает child.Parent уже загруженным в контекст, и однократной установки на ноль должно быть достаточно.

...