tags:

views:

205

answers:

1

I have one bit of denormalized data used for performance reasons and I'm trying to maintain the data with an NHibernate event listener rather than a trigger. I'm not convinced this is the best approach, but I'm neck deep into it and I want to figure this out before moving on. I'm getting following error:

System.InvalidOperationException : Collection was modified; enumeration operation may not execute. 
    System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) 
    System.Collections.Generic.List`1.Enumerator.MoveNextRare() 
    System.Collections.Generic.List`1.Enumerator.MoveNext() 
    NHibernate.Engine.ActionQueue.ExecuteActions(IList list) 
    NHibernate.Engine.ActionQueue.ExecuteActions() 
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (IEventSource session) 
    NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) 
    NHibernate.Impl.SessionImpl.Flush() 
    NHibernate.Transaction.AdoTransaction.Commit()

Here's the code to make happen:

using (var tx = session.BeginTransaction()) 
{ 
    var business = session 
        .Get<Business>(1234) 
        .ChangeZipCodeTo("92011"); 
    session.Update(business); 
    tx.Commit(); // error happens here 
}

and the event listener:

public void OnPostUpdate(PostUpdateEvent @event) 
{ 
    var business = @event.Entity as Business; 
    if (business != null) 
    { 
        var links = @event.Session 
            .CreateQuery("select l from BusinessCategoryLink as l where l.Business.BusinessId = :businessId") 
            .SetParameter("businessId", business.BusinessId) 
            .List<BusinessCategoryLink>();

        foreach (var link in links) 
        { 
            link.Location = business.Location; 
            @event.Session.Update(link); 
        } 
    } 
}
+1  A: 

This doesn't look like it's related to NHibernate, but rather the way C# handles iterators, and specifically Enumerations. I'm kind of guessing, but I think it's because you're modifying the value of an enumeration on this line: link.Location = business.Location;. A quick google search tells me that the Enumerator.Current property is read-only (which is what is used when you use the foreach construct). I bet using a regular for loop will solve this problem.

tmont
I've seen that kind of error when trying to remove an item from a list while doing a foreach over it, but I don't see why it's a problem in this case. Clearly I'm doing something wrong, so an old fashioned for loop is worth a shot. If only I could remember how to write one of those...
Michael Valenty
This is definitely an issue with NHibernate. If you do a Google search you'll find others with it. The problem is that you're modifying the list of actions NHibernate needs to carry out when you do the .Update call.
ShaneC