开发者

System.InvalidOperationException when trying to iteratively add objects using EF 4

This question is very similiar to this one. However, the resolution to that question:

  1. Does not seem to apply, or
  2. Are somewhat suspect, and don't seem like a good approach to resolving the problem.

Basically, I'm iterating over a generic list of objects, and inserting them. Using MVC 2, EF 4 with the default code generation.

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

And the Repository.Add() method:

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

I should note that I've been successfully using the Add() method throughout my code for single inserts; this is the first time I've tried to use it to iteratively insert a group of objects.

The error:

System.InvalidOperationException: The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.

As stated in the prior question, the EntityKey is set to True, StoreGeneratedPattern = Identity. The actual table that is being inserted into is a relationship table, in that it is comprised of an identity field and two foreign key fields. The error always occurs on the second insert, regardless of whether that specific entity has been inserted before or not, and I can confirm that the values are always different, no key conflicts as far as the database is concerned. My suspicion is that it has something to do with the temporary entitykey that gets set prior to the actual insert, but I don't know how to confirm that, nor do I know how to resolve it.

My gut feeling is that the solution in the prior question, to set the SaveOptio开发者_如何学JAVAns to None, would not be the best solution. (See prior discussion here)


I've had this issue with my repository using a loop as well and thought that it might be caused by some weird race-like condition. What I've done is refactor out a UnitOfWork class, so that the repository.add() method is strictly adding to the database, but not storing the context. Thus, the repository is only responsible for the collection itself, and every operation on that collection happens in the scope of the unit of work.

The issue there is that: In a loop, you run out of memory damn fast with EF4. So you do need to store the changes periodically, I just don't store after every save.

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

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

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

Then you can do something like

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();

Note: I don't really like this solution, but I hunted around to try to find why things break in a loop when they work elsewhere, and that's the best I came up with.


We have had some odd collision issues if the entity is not added to the context directly after being created (before doing any assignments). The only time I've noticed the issue is when adding objects in a loop.

Try adding the newed up entity to the context, do the assignments, then save the context. Also, you don't need to save the context each time you add a new entity unless you absolutely need the primary key.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜