Проблемы EF4 с MVC - EntityKey, отношения «многие ко многим» и т. Д. Какую основную истину я упускаю? - PullRequest
2 голосов
/ 24 июня 2011

Я пытался заставить EF4 работать с проектом MVC 2 уже около шести месяцев.Это было упражнение в пытках.Попытка сделать что-нибудь нетривиальное требует жонглирования EntityKeys, выполнения танца ObjectContext Attach / Detach и, действительно, попытки угадать необходимую черную магию, чтобы заставить ее работать, основываясь на расплывчатых, в основном бесполезных сообщениях об исключениях.Сказать, что это разочаровывает, - это огромное, огромное преуменьшение.

Итак, отвлекись, вот моя проблема: у меня есть довольно сложная модель, которую я пытаюсь создавать / редактировать с помощью форм.Хотя большая часть данных представляет собой простые скаляры, в ней также есть данные многие-ко-многим.Сайт будет (если я когда-нибудь закончу ...) сайтом обзора видеоигр.Таким образом, отношение «многие ко многим» является одним из отношений между Играми и платформами, на которых они доступны (XBox 360, PS3 и т. Д.).Платформы выбираются с помощью флажков, причем каждый флажок связан с определенным идентификатором платформы.

Чтобы попытаться сделать все правильно, я привязываюсь к модели редактирования, прежде чем перенести данные в настоящую игру.и объекты платформы.После передачи данных я вызываю свой метод Save в своем хранилище, который на самом деле является просто оболочкой для моего ObjectContext.

public void SaveGame(Game game)
{
    _siteDB.Games.Attach(game);

    if (game.GameID > 0)
    {
        _siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Modified);
    }
    else
    {
        _siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Added);
    }

    _siteDB.SaveChanges();
}

Прямо сейчас я сталкиваюсь с ошибками в моем операторе Attach.Там, где он находится, я получаю исключение, сообщающее, что ObjectContext не может отслеживать два объекта с одним и тем же ключом EntityKey.Если я удаляю его, я получаю исключение, сообщающее, что для игры требуется EntityKey.Я попытался использовать ApplyCurrentValues, но затем столкнулся с похожими проблемами, пытаясь добавить платформы.

В конечном счете, кажется, что есть один конкретный шаблон, который нужно использовать, чтобы заставить что-то подобное работать.Кажется, я просто могу понять, что это такое, и это очень расстраивает.Я просто не вижу решения, которое бы не требовало, чтобы я разрушил разделение между моим пользовательским интерфейсом и внутренним интерфейсом.

Может кто-нибудь указать мне правильное направление?Существуют ли какие-либо учебные пособия по MVC / EF4, которые имеют дело с более сложными вещами, чем знаменитые примеры demoware?


РЕДАКТИРОВАТЬ: Достигнут некоторый прогресс в следующем:

public void SaveGame(Game game)
{
    if (game.GameID > 0)
    {
        var editedGame = this.GetGame(game.GameID);

        var eSet = editedGame.EntityKey.EntitySetName;
        _siteDB.ApplyCurrentValues(eSet, game);

        var existingPlats = editedGame.Platforms.ToArray();

        foreach (var plat in existingPlats)
        {
            editedGame.Platforms.Remove(plat);
        }

        var newPlats = game.Platforms.ToArray();

        foreach (var nPlat in newPlats)
        {
            editedGame.Platforms.Add(nPlat);
        }

        game = null;

        _siteDB.ObjectStateManager.ChangeObjectState(editedGame, System.Data.EntityState.Modified);
    }
    else
    {
        _siteDB.Games.AddObject(game);
    }

    _siteDB.SaveChanges();
}

Моя единственная проблема сейчасявляется то, что он добавляет game к ObjectContext, даже если я устанавливаю его на ноль.Итак, моя существующая сущность обновляется нормально, но я также получаю новую зеркальную сущность, вставленную в БД.

1 Ответ

2 голосов
/ 24 июня 2011

Проблема в том, что у вас уже есть Game в контексте с тем же идентификатором.Вы не можете иметь два объекта с одинаковым идентификатором.

То, как вы попали в это состояние, является функцией кода, который вы не показываете.Но давайте поговорим о решении вашей непосредственной проблемы.По сути, существует два подхода:

  1. Отсоединение существующего объекта или
  2. Сохранение существующего объекта и копирование значений из нового объекта (тот, который вы передаете какАргумент).

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

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