Обновить исключение с помощью Entity-Framework? - PullRequest
3 голосов
/ 13 декабря 2010

Привет

Я использую EntityFramework для своего веб-сайта ASP.NET MVC, но у меня есть некоторые проблемы с обновлением.

Вот так выглядит мой код обновления:

using (BissEntities context = new BissEntities())
    {

      if (adCategoryFilter.Id < 1)
        context.AddToAdCategoryFilter(adCategoryFilter);
      else
        context.Refresh(System.Data.Objects.RefreshMode.ClientWins, adCategoryFilter);

      if (context.SaveChanges() > 0)
        return true;
    }
    return false;

При выполнении context.Refresh я получаю следующее исключение:

Элемент с индексом 0 в коллекции объектов для обновления имеет нулевое значение свойства EntityKey или не прикреплен к этому ObjectStateManager.

Stacktrace :    at System.Data.Objects.ObjectContext.RefreshCheck(Dictionary`2 entities, Object entity, EntityKey key)
   at System.Data.Objects.ObjectContext.AddRefreshKey(Object entityLike, Dictionary`2 entities, Dictionary`2 currentKeys)
   at System.Data.Objects.ObjectContext.RefreshEntities(RefreshMode refreshMode, IEnumerable collection)
   at System.Data.Objects.ObjectContext.Refresh(RefreshMode refreshMode, Object entity)
   at Biss.Models.FilterModel.UpdateCategoryFilter(AdCategoryFilter adCategoryFilter) in C:\Users\Snowman\Documents\Visual Studio 2010\Projects\Biss\Biss\Models\FilterModel.cs:line 86 

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

Откуда поступил фильтр adCategoryFilter?

Объект adCategoryFilter создается (новый), а затем заполняется данными из ViewObject (с веб-сайта). Он имеет необходимые данные, такие как идентификатор фильтра (для сопоставления фильтра с правильной строкой в ​​дБ).

Прошу объяснить, почему у меня возникла эта проблема и как я мог ее решить.

BestRegards

Ответы [ 2 ]

5 голосов
/ 14 декабря 2010

Поскольку вы используете ASP.NET MVC, вы работаете в среде без состояний .Это означает, что после того, как запрос завершит обработку, больше не будет «Память Entity Framework» или «График».

Итак, вам нужно явно указать EF, что вы хотите добавить или обновить.

Вот как это делается:

using (BissEntities context = new BissEntities())
{
  if (adCategoryFilter.Id < 1)
    context.AdCategoryFilters.AddObject(adCategoryFilter);
  else {
     var stub = new AdCategoryFilters { Id = adCategoryFilter.Id };
     context.AdCategoryFilters.Attach(stub);
     context.AdCategoryFilters.ApplyCurrentValues(adCategoryFilter);
  }

  context.SaveChanges();
}

Это называется техникой заглушки .

Короче говоря, вы создаете новую сущность с тем же самымключ сущности как сущность, которую вы пытаетесь ОБНОВИТЬ (в вашем случае ключ сущности равен «Id»).

Затем вы «присоединяете» эту заглушку (так, чтобы она отслеживалась внутренним графом EF), затем переопределяетезначения в этой заглушке с вашей сущностью UPDATE, затем сохраните изменения.

Я не могу использовать UpdateModel , так как у меня многоуровневая архитектура и я использую POCO, пользовательские модели представления и т. д.- поэтому я создал собственный метод «UpdateModel» в своем сервисе / репозитории - который выполняет (более сложную) версию выше.

Также старайтесь не использовать «если Id <1, это дополнение»с ASP.NET MVC - как если бы вы забыли привязать идентификатор на представлении, он будетбудет передаваться как 0, так что даже если вы можете делать <strong>обновление , приведенный выше код попытается сделать add .

Вместо этого будьте более явными - используйте отдельные методы действий для добавления / обновления.

HTH.

4 голосов
/ 13 декабря 2010

Вместо обновления, попробуйте получить объект и обновить его свойства, используя что-то вроде автоматического сопоставления (или UpdateModel в контроллере MVC)

EntityKey - это отдельная вещь для свойства id, с некоторыми другими вещами, происходящими под капотом. В вашем вновь созданном объекте отсутствует этот материал, из-за которого и возникает проблема.

Шаблон немного похож (не парень C #, поэтому, пожалуйста, извините синтаксис):

var context = new MyEntities();
var originalObject = context.MyObjectSet.Single(x => x.Id == viewmodel.Id);
UpdateModel(originalObject);
context.SaveChanges();

Принципиальным отличием является то, что вновь найденный объект правильно настроил EntityKey. Вы можете правильно использовать свойство id для обнаружения нового / существующего объекта, но EntityKey - это не только это свойство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...