简体   繁体   中英

Entity With EntityState.Added Not Returned In IRepository<T>.FindAll()

I'm working on a small application that lets users create a list of words and the user is able to provide a name for the list. I setup the program to take advantage of the Unit of Work pattern. I want the user to be able to make all CRUD changes they want, then when the user is ready to update the database, click a "Save Changes" button to do Context.SaveChanges() and make all the changes.

I'm using Entity Framework with the Repository & Unit of Work patterns with Lazy Loading enabled. The list and word classes are both POCOs mapped to a data model which is in turn mapped from a database.

My Add Code:

_unitOfWork.ListRepository.Add(newList);

The ListRepository.Add method:

public void Add(T newEntity)
{
    _objectSet.AddObject(newEntity);
}

Later on I get an InvalidOperationException with the message: Sequence contains no elements.

_unitOfWork.ListRepository.Find(l => l.Name == currentName).Single();

I know why I get that exception because I should use SingleOrDefault() to be safe. However, I KNOW the entity I'm looking for exists some where in the context. My guess is that I'm not searching in the right place.

Here's the rub (or my lack of knowledge):

During a debug, I put a breakpoint on the above _unitOfWork.ListRepository.Add(newList) code. After a Step-Over, I went to the Immediate Window and did and got the following:

?_unitOfWork.ListRepository.FindAll().Count();
1

The "1" is supposed to be a "2"

The ListRepository.FindAll() method:

public IQueryable<T> FindAll()
{
    return _objectSet;
}

I've traced through my code and I'm only initializing my _unitOfWork object once. I exposed the ObjectSet.Context.ObjectStateManager in the repository, and when the exception assistant comes up in debug, I can go to the Immediate Window and do:

_unitOfWork.ListRepository.GetObjectStateManager()
    .GetObjectStateEntries(EntityState.Added).Count();
1

So, I know the entity is in there but I'm not sure how to get at it using the _unitOfWork or ListRepository objects. Any assistance would be appreciated or please point me in the right direction.

Thanks.

That is how EF behaves. Your Find and FindAll access ObjectSet instance. This will always make query to the database - it does nothing with entities created and not yet inserted to database and they cannot be part of returned result.

To get entities which are not yet persisted you must search in ObjectStateManager . You can add this to your repository to allow searching for single entity. It will first search internal EF storage and if entity will not be found it will search the database:

private T SearchStateManager(Expression<Func<T, bool>> searchCriteria)
{
    return _context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached)
                                      .Where(e => !e.IsRelationship)
                                      .Select(e => e.Entity)
                                      .OfType<T>()
                                      .SingleOrDefault(searchCriteria.Compile());
} 

public T Single(Expression<Func<T, bool>> searchCriteria)
{
    T entity = SearchStateManager(searchCriteria);
    if (entity == null)
    {
        entity = _objectSet.SingleOrDefault(searchCriteria);
    }

    return entity;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM