System.InvalidOperationException при попытке итеративно добавлять объекты с помощью EF 4 - PullRequest
4 голосов
/ 13 января 2011

Этот вопрос очень похож на этот . Однако решение этого вопроса:

  1. Не похоже, или
  2. Несколько подозрительны и не кажутся хорошим подходом к решению проблемы.

По сути, я перебираю общий список объектов и вставляю их. Использование MVC 2, EF 4 с генерацией кода по умолчанию.

foreach(Requirement r in requirements)
{
    var car = new CustomerAgreementRequirement();
    car.CustomerAgreementId = viewModel.Agreement.CustomerAgreementId;
    car.RequirementId = r.RequirementId;
    _carRepo.Add(car); //Save new record
}

И метод Repository.Add ():

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private TxRPEntities txDB;
    private ObjectSet<TEntity> _objectSet;        

    public void Add(TEntity entity)
    {
        SetUpdateParams(entity);
        _objectSet.AddObject(entity);
        txDB.SaveChanges();
    }

Я должен отметить, что я успешно использовал метод Add () по всему коду для одиночных вставок; это первый раз, когда я пытался использовать его для итеративной вставки группы объектов.

Ошибка:

System.InvalidOperationException: изменения в базе данных были успешно приняты, но произошла ошибка при обновлении контекста объекта. ObjectContext может быть в несовместимом состоянии. Внутреннее сообщение об исключении: AcceptChanges не может продолжаться, потому что значения ключа объекта конфликтуют с другим объектом в ObjectStateManager. Убедитесь, что значения ключей являются уникальными, прежде чем вызывать AcceptChanges.

Как указано в предыдущем вопросе, для EntityKey задано значение True, StoreGeneratedPattern = Identity. Фактическая таблица, в которую вставляется таблица, представляет собой таблицу отношений, в которой она состоит из поля идентификатора и двух полей внешнего ключа. Ошибка всегда возникает при вставке second , независимо от того, была ли эта конкретная сущность вставлена ​​ранее или нет, и я могу подтвердить, что значения всегда различны, никакие ключи не конфликтуют с базой данных. Я подозреваю, что это как-то связано с временным ключом, который устанавливается до фактической вставки, но я не знаю, как это подтвердить, и не знаю, как его разрешить.

Мне кажется, что решение предыдущего вопроса - установить для параметра SaveOptions значение None - не лучшее решение. (См. Предварительное обсуждение здесь )

Ответы [ 2 ]

1 голос
/ 12 мая 2011

У меня была эта проблема с моим репозиторием, использующим также цикл, и я подумал, что это может быть вызвано каким-то странным расообразным состоянием. Я выполнил рефакторинг класса UnitOfWork, чтобы метод repository.add () строго добавлялся в базу данных, но не сохранял контекст. Таким образом, хранилище отвечает только за саму коллекцию, и каждая операция над этой коллекцией происходит в объеме единицы работы.

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

открытый класс BaseRepository: IRepository, где TEntity: class { частный TxRPEntities txDB; private ObjectSet _objectSet;

public void Add(TEntity entity)
{
    SetUpdateParams(entity);
    _objectSet.AddObject(entity);
}

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

Тогда вы можете сделать что-то вроде

foreach(Requirement r in requirements)
{
    var car = new CustomerAgreementRequirement();
    car.CustomerAgreementId = viewModel.Agreement.CustomerAgreementId;
    car.RequirementId = r.RequirementId;
    _carRepo.Add(car); //Save new record
    if (some number limiting condition if you have thousands)
        _carRepo.Save(); // To save periodically and clear memory
}

_carRepo.Save();

Примечание: мне не очень нравится это решение, но я искал, чтобы попытаться выяснить, почему что-то прерывается, когда они работают в другом месте, и это лучшее, что я придумал.

0 голосов
/ 20 апреля 2011

У нас были некоторые странные проблемы столкновения, если объект не был добавлен в контекст сразу после его создания (перед выполнением каких-либо назначений).Единственный раз, когда я заметил проблему, это при добавлении объектов в цикле.

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

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