Вопрос по entity-framework, asp.net-mvc – Ограничение внешнего ключа, EF с коллекцией дочерних объектов

0

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

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

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

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

Update Добавлен код

<code>[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();
}
</code>

Больше код:

<code>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; }
}
</code>

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

Another update Я успешно удалил ошибку, изменив MagnetEventId в AttendeeInformationField на null-значение int. При изучении базы данных я вижу, что именно не так.

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

Я бы очень предпочел, чтобы посты в AttendeeInformationField были обновлены.

Можете ли вы опубликовать свой запрос и обновить код? Luke McGregor
Конечно, я обновил исходное сообщение. Stefan Bergfeldt

Ваш Ответ

4   ответа
0

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

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

Из того, что я понимаю, виртуальный означает стремительную загрузку, так что да! Из того поста, на который я ссылался, я думаю, что это как-то связано с моей коллекцией ICollection <AttendeeInformationField> При отладке все выглядит нормально, но сохранить не удается Stefan Bergfeldt
Извините, это моя ошибка. У меня Ленивая загрузка на. Когда я отлаживаю, я вижу все значения. Stefan Bergfeldt
Virtual означает, что он может загружаться Lazy, если включен. Eagerload - это когда вы говорите, что он включает в себя ассоциации. Если вы отлаживаете, Find (...) дает вам clss без нулевых значений в id и в ассоциациях? RockJohan
0

который ты называешь оригинальным.

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

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

Еще одна проблема заключается в том, что я не вижу, если eventRepository.Save ();

действительно делаете SaveShages? Является ли? Я могу найти некоторый контекстный код в другом методе Save?

Я обновил свой оригинальный пост. Stefan Bergfeldt
0

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

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

Да, и LocationId, и CustomerId имеют правильные значения при отладке. Все работало хорошо, пока я не попытался реализовать ICollection <AttendeeInformationField> Stefan Bergfeldt
Я добавил больше информации в исходное сообщение Stefan Bergfeldt
0

это ошибка (?) В ASP.NET MVC, когда дело доходит до UpdateModel и модели, содержащей ICollection.

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

Обновит Я нашел решение! Вышеуказанное работало только при обновлении существующих элементов в коллекции. Чтобы решить эту проблему, я должен вручную проверить и добавить новые поля 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 это на самом деле работает как с редактированием, так и с добавлением. Пока я не пытался удалить.

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

Похожие вопросы