EF ограничения внешнего ключа и шаблон репозитория - PullRequest
0 голосов
/ 03 августа 2011

У меня есть этот простой метод удаления Get и Post в приложении asp.net mvc

public ActionResult Delete(int ehrId, int id)
        {
            EHR ehr = ehrRepository.FindById(ehrId);
            PhysicalTest test = ehr.PhysicalTests.Where(t => t.ID == id).Single();
            return View(test);
        }


        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int ehrId, int id)
        {
            EHR ehr = ehrRepository.FindById(ehrId);
            PhysicalTest test = ehr.PhysicalTests.Where(t => t.ID == id).Single();
            ehr.PhysicalTests.Remove(test);
            unitOfWork.Commit();
            TempData["Success"] = "You have deleted the Physical Test Succesfully";
            return RedirectToAction("Index");
        }

проблема в том, что когда я пытаюсь удалить дочерний объект таким способом, EF будет жаловаться

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

Один из ответов - использовать репозиторий PhysicalTest (дочерний элемент) вместо EHRRepository ... но это не похоже на хорошее решение, потому что я хочу обеспечить безопасность, всегда запрашивая через родительский объект, чтобы пользователь не редактировал / удаляя физический тест, который ему не принадлежит.

Я бы хотел ограничить свои репозитории только совокупностью корней.

Вот моя текущая общая реализация SqlRepository .... Я открыт для предложений.

public class SqlRepository<T> : IRepository<T>
                                    where T : class, IEntity {

        internal SummumnetDB context;
        internal DbSet<T> _objectSet;

        public SqlRepository(SummumnetDB context)
        {
            this.context = context;
            this._objectSet = context.Set<T>();
        }


       public IQueryable<T> Find(Expression<Func<T, bool>> predicate) {
            return _objectSet.Where(predicate);
        }

        public void Add(T newEntity) {
            _objectSet.Add(newEntity);
        }

        public void Remove(T entity) {
            _objectSet.Remove(entity);
        }

        public IQueryable<T> FindAll()
        {
            return _objectSet;
        }

        public T FindById(int id)
        {
            return _objectSet.Single(o => o.ID == id);
        }


    }

1 Ответ

0 голосов
/ 03 августа 2011

Ваши EHR и PhysicalTest образуют агрегат, где EHR является агрегированным корнем для PhysicalTest, поскольку PhyscialTest не может существовать без EHR (ваше исключение говорит, что FK в PhysicalTest не может быть нулевым). Репозиторий должен существовать для совокупного корня и предлагать конкретный метод для работы с отношениями.

Да, это не будет универсальным, потому что универсальный подход для сущностей с различными конфигурациями и требованиями не работает.

В чем проблема с вашим кодом? Вызов ehr.PhysicalTests.Remove(test) не удалит тест. Он только устанавливает его FK на ноль. Чтобы удалить test, вы должны действительно позвонить context.DeleteObject(test). Чтобы разрешить прямое удаление, вы должны использовать идентифицирующее отношение .

...