Ограничение внешнего ключа, EF с коллекцией дочерних объектов

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

Насколько я понимаю из Связь не может быть изменена, поскольку одно или несколько свойств внешнего ключа не допускают значения NULL проблема может заключаться в том, как Entity Framework обрабатывает мою виртуальную коллекцию ICollection

Однако я не совсем уверен, как реализовать решение при использовании шаблона репозитория с шаблоном. Надо ли редактировать метод Save () класса ParentObjectRepository?

На самом деле я действительно думаю, что должен быть какой-то способ заставить EF это понять. Я не понимаю, как думала команда EF: «Вероятно, никто не использует коллекцию объектов с ограничением внешнего ключа, давайте не будем поддерживать это».

Обновить Добавлен код

[HttpPost]
public ActionResult Edit(int id, FormCollection formCollection)
{
    var eventRepository = new MagnetEventRepository();
    var original = eventRepository.Find(id);
    UpdateModel(original);
    eventRepository.Save();
    return RedirectToAction("Details", "Home", new { slug = original.Slug });
}

public void Save()
{
    context.SaveChanges();
}

Больше кода:

public class MagnetEvent
{
    public virtual int Id { get; set; }

    [Required]
    public virtual string Name { get; set; }

    [Required]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm}")]
    [DataType(DataType.DateTime)]
    public virtual DateTime? StartDate { get; set; }

    public virtual string Description { get; set; }

    [StringLength(100)]
    public virtual string Slug { get; set; }

    public virtual int MaximumCapacity { get; set; }

    [DataType(DataType.Currency)]
    public virtual int TicketPrice { get; set; }

    public virtual int LocationId { get; set; }
    public virtual Location Location { get; set; }

    public virtual Collection<Ticket> Tickets { get; set; }

    public virtual Collection<AttendeeInformationField> CaptureAttendeeInformationFields { get; set; }

    public virtual int CustomerId { get; set; }

    [Required]
    public virtual CUSTOMER Customer { get; set; }
}

Метод Save () взят из MagnetEventRepository, созданного на основе вышеуказанного класса.

Другое обновление. Я успешно удалил ошибку, изменив MagnetEventId в AttendeeInformationField на nullable int. Изучая базу данных, я вижу, что именно не так.

Допустим, у меня есть одно поле AttendeeInformationField со значением «Электронная почта». Когда я редактирую свой MagnetEvent, AttendeeInformationField обновляет MagnetEventId до нуля, а затем добавляет новый пост с правильными MagnetEventId и Value.

Я бы очень предпочел, чтобы вместо этого обновлялись сообщения в AttendeeInformationField.


person Stefan Bergfeldt    schedule 16.04.2012    source источник
comment
Можете ли вы опубликовать свой запрос и обновить код?   -  person Not loved    schedule 16.04.2012
comment
Конечно, я обновил исходный пост.   -  person Stefan Bergfeldt    schedule 16.04.2012


Ответы (4)


Можете ли вы добавить код для вашего объекта события. Тот, который вы называете оригинальным.

Может случиться так, что UpdateModel изменит некоторую информацию о связанных объектах, и это нехорошо, если так. Не уверен в этом, хотя я не могу видеть весь код.

Я предпочитаю не использовать UptadeModel, а вместо этого использовать модель ввода или вашу модель MVC в качестве параметра in и вручную сопоставлять изменения с загруженным исходным объектом.

Другая проблема в том, что я не вижу, если eventRepository.Save ();

действительно сделать SaveShages? Имеет ли это? Я могу использовать какой-то контекстный код в другом методе Сохранить?

person RockJohan    schedule 16.04.2012

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

Вы с нетерпением загружаете связанные объекты? нравится клиент?

person RockJohan    schedule 16.04.2012
comment
Насколько я понимаю, виртуальный означает нетерпеливую загрузку, так что да! Из того сообщения, на которое я ссылался, я думаю, что это как-то связано с моей ICollection ‹AttendeeInformationField› При отладке все в порядке, но не удается сохранить - person Stefan Bergfeldt; 16.04.2012
comment
Виртуальный означает, что он может выполнять ленивую загрузку, если он включен. Eagerload - это когда вы говорите, что он должен включать ассоциации. Если вы отлаживаете, дает ли Find (...) вам clss без нулевых значений в id и в ассоциациях? - person RockJohan; 16.04.2012
comment
Извини, я виноват. У меня включена отложенная загрузка. Когда я отлаживаю, я вижу все значения. - person Stefan Bergfeldt; 16.04.2012

Следует отметить, что у вас не должно быть [Required] для клиента, поскольку это выводится из того факта, что ваш FK не может быть пустым. Обязательно следует использовать в свойстве навигации, только если у вас нет FK в модели.

Чтобы попытаться диагностировать проблему, можете ли вы загрузить объект и посмотреть его в отладчике, вы должны ожидать, что и locationId, и CustomerId имеют ненулевые значения.

person Not loved    schedule 16.04.2012
comment
Да, и LocationId, и CustomerId имеют правильные значения при отладке. Все работало хорошо, пока я не попытался реализовать ICollection ‹AttendeeInformationField› - person Stefan Bergfeldt; 16.04.2012
comment
Я добавил больше информации в исходный пост - person Stefan Bergfeldt; 16.04.2012

Я нашел решение своей проблемы. Кажется, это ошибка (?) В ASP.NET MVC, когда дело касается UpdateModel и модели, содержащей ICollection.

Решение состоит в том, чтобы переопределить поведение по умолчанию, как описано в этом сообщении блога: http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx

Обновление Я нашел решение! Вышеупомянутое работало только при обновлении существующих элементов в коллекции. Чтобы решить эту проблему, мне нужно вручную проверить и добавить новые поля AttendeeInformationFields. Нравится:

[HttpPost]
public ActionResult Edit(int id, MagnetEvent magnetEvent)
{
    var eventRepository = new MagnetEventRepository();
    var original = eventRepository.Find(id);
    UpdateModel(original);
    foreach (var attendeeInformationField in magnetEvent.CaptureAttendeeInformationFields)
    {
        var attendeeInformationFieldId = attendeeInformationField.Id;
        if (original.CaptureAttendeeInformationFields.AsQueryable().Where(ai => ai.Id == attendeeInformationFieldId).Count() == 0)
        {
            original.CaptureAttendeeInformationFields.Add(attendeeInformationField);
        }
    }
    eventRepository.Save();
}

Вместе с измененным DefaultModelBinder это действительно работает как с редактированием, так и с добавлением. Пока не пробовал удалять.

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

person Stefan Bergfeldt    schedule 17.04.2012