Question

I have a list of Item entities that are being processed in a batch, something like this:

foreach (var itemId in ItemIdList)
{
    var item = getById(itemId); //load line
    if(item != null)
    {
      //...do some processing 
      delete(item)
    }
}

The problem is, the same itemId could be listed in ItemIdList multiple times, so after it is deleted, and I try to load the item a second time, the load line fails with the error

Unexpected row count: 0; expected: 1  (stale state exception)

I understand that the entity is not there any more, but I would have expected my get function to just return null. Here is my getById function:

var item = (from i in UnitOfWork.CurrentSession.QueryOver<T>()
                        where i.Id == id
                        select i
                        ).SingleOrDefault();

Why isn't SingleOrDefault just returning null?

My Item entity only has one autogenerated key and the hash function looks like this:

public override int GetHashCode()
    {
        int hashCode = 0;

        hashCode = hashCode ^ Id.GetHashCode();

        return hashCode;
    }

Edit:

Here is my delete method

    public void Delete(T t) //T would be Item in this case
    {
       UnitOfWork.CurrentSession.Delete(t);
    }
Was it helpful?

Solution

I haven't seen your delete method but since you state these items are being done in a 'batch' I'll assume you wait to flush until everything has been deleted.

Since the flush doesn't occur until you've attempted to delete all the items, it still exists in the database. Therefore, when you retrieve the item a second time it thinks that it should be 'deleted' but, behold, it still exists. This is why NHibernate thinks that the state is 'stale.'

One easy way to fix this would be to have the ItemIdList be a set (like a HashSet). This will prevent duplicate IDs from being present and should fix the problem.

On another note, if you are attempting to delete all entities within a list of ids, there are a lot more efficient ways than reading each one, one at a time, from the database and then deleting them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top