Как обновить сложную модель в ASP.NET MVC 3 - PullRequest
6 голосов
/ 14 января 2012

Я пытаюсь обновить сложную модель в одном представлении. Я использую ASP.NET MVC3, Entity Framework с кодом в первую очередь, единицу работы, общий шаблон хранилища .. но когда я пытаюсь обновить модель, я получаю эту ошибку:

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

Вот моя упрощенная модель:

public class TransactionViewModel
{
     public Transaction Transaction { get; set; }
     public bool IsUserSubmitting { get; set; }
     public IEnumerable<SelectListItem> ContractTypes { get; set; }
}

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

public class Transaction
{
    [Key]
    public int Id { get; set; }

    public int CurrentStageId { get; set; }

    public int? BidId { get; set; }

    public int? EvaluationId { get; set; }

    public virtual Stage CurrentStage { get; set; }

    public virtual Bid Bid { get; set; }

    public virtual Evaluation Evaluation { get; set; }

}

public class Bid
{
    [Key]
    public int Id { get; set; }

    public string Type { get; set; }

    public DateTime? PublicationDate { get; set; }

    public DateTime? BidOpeningDate { get; set; }

    public DateTime? ServiceDate { get; set; }

    public string ContractBuyerComments { get; set; }

    public string BidNumber { get; set; }

    public DateTime? ReminderDate { get; set; }

    public DateTime? SubmitDate { get; set; }

}

Используя ту же модель представления, я могу создать объект транзакции, который будет заполнять базу данных следующим образом.

Id: 1, CurrentStageId: 1, BidId: 1, EvaluationId: 1

но, когда я пытаюсь обновить свойства в этих свойствах навигации, эта строка вызывает ошибку в контроллере:

[HttpPost]
public ActionResult Edit(TransactionViewModel model)
{
    if (ModelState.IsValid)
    {
        -> unitOfWork.TransactionRepository.Update(model.Transaction);
           unitOfWork.Save();
           return RedirectToAction("List");
    }
}

В общем хранилище:

public virtual void Update(TEntity entityToUpdate)
{
 -> dbSet.Attach(entityToUpdate);
    context.Entry(entityToUpdate).State = EntityState.Modified;
}

Проблема еще более усложняется, потому что я должен иметь возможность редактировать любые поля (свойства) в любом из свойств навигации в объекте Transaction в одном представлении.

1 Ответ

12 голосов
/ 14 января 2012

Я считаю, что исключение означает следующее:

Значения свойств, которые определяют ссылочные ограничения ... (это значение свойства первичного ключа (= Id)Bid и значение свойства внешнего ключа (= BidId) Transaction)

... не согласованы ... (= имеют разные значения)

... между основным ... (= Bid)

... и зависимым ... (= Transaction)

... объекты в отношениях.

Итак, это выглядит следующим образом: Когда связыватель модели MVC создает TransactionViewModel в качестве параметра для Editaction, model.Transaction.BidId и model.Transaction.Bid.Id различны, например:

  • model.Transaction.BidId.HasValue равно true, но model.Transaction.Bid равно null
  • model.Transaction.BidId.HasValue равно false, но model.Transaction.Bid не является null
  • model.Transaction.BidId.Value! = model.Transaction.Bid.Id

(Первый пункт, вероятно, не проблема.Я думаю, что у вас есть ситуация 2.)

То же самое относится к CurrentStage и Evaluation.

Возможные решения:

  • Установите эти свойства на те же значения, прежде чем вызывать метод Update вашего хранилища (= хак)
  • Bind TransactionViewModel.Transaction.BidId и TransactionViewModel.Transaction.Bid.Id к двум скрытым полям формы с одинаковым значением, чтобы связыватель модели заполнил оба свойства.
  • Используйте также ViewModel для внутреннего свойства Transaction (а также для свойств навигации внутри Transaction)который адаптирован к вашему виду и который вы можете соответственным образом сопоставить с сущностями в действии вашего контроллера.

И последнее, что следует упомянуть, это то, что эта строка ...

context.Entry(entityToUpdate).State = EntityState.Modified;

... не помечает связанные объекты (Transaction.Bid) как измененные, поэтому не сохраняет никаких изменений Transaction.Bid.Вы также должны установить состояние для связанных объектов Modified.

Примечание: если у вас нет дополнительного сопоставления с Fluent API для EF, все ваши отношения не один-к-одному, аодин ко многим, потому что у вас есть отдельные свойства FK.Отношения «один к одному» с EF требуют общих первичных ключей.

...