IndexOutOfRange exception when disposing of adapter between two queries

Posts   
 
    
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 31-Mar-2008 18:20:37   

Hi Frans

This isn't linq related, but this issue seems to have cropped up with the latest beta build. This code throws an IndexOutOfRangeException:


DataAccessAdapter adapter = new DataAccessAdapter();

EntityCollection<CustomerEntity> customers1 = new EntityCollection<CustomerEntity>();
EntityCollection<CustomerEntity> customers2 = new EntityCollection<CustomerEntity>();

RelationPredicateBucket bucket = new RelationPredicateBucket(CustomerFields.ContactTitle == "Owner");
RelationPredicateBucket bucket1 = new RelationPredicateBucket(CustomerFields.City == "México D.F.");

adapter.FetchEntityCollection(customers1, bucket);
adapter.Dispose();

adapter.FetchEntityCollection(customers2, bucket1);
adapter.Dispose();

If I remove the first call to adapter.Dispose() then this works correctly.

The stack trace:


   at SD.LLBLGen.Pro.ORMSupportClasses.UniqueList`1.AddOrGet(T item)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.ReadRowIntoFields(Object[] values, IEntityFields2 rowDestination, List`1 fieldIndexToOrdinal, IFieldPersistenceInfo[] fieldsPersistenceInfo)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.ExecuteMultiRowRetrievalQuery(IRetrievalQuery queryToExecute, IEntityFactory2 entityFactory, IEntityCollection2 collectionToFill, IFieldPersistenceInfo[] fieldsPersistenceInfo, Boolean allowDuplicates, IEntityFields2 fieldsUsedForQuery)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollectionInternal(IEntityCollection2 collectionToFill, IRelationPredicateBucket& filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, ExcludeIncludeFieldsList excludedIncludedFields, Int32 pageNumber, Int32 pageSize)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, Int32 pageNumber, Int32 pageSize)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket)
   at Northwind.Program.Main(String[] args) in C:\Documents\Desktop\Northwind\Program.cs:line 28
   at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 31-Mar-2008 20:37:06   

It's a debatable issue. I think any call after 'Dispose()' should throw an exception that the object has already been disposed. Though that would add a lot of checks to the methods. Perhaps I can add a better check in a more central place like the open/close of the connection simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 31-Mar-2008 21:41:03   

Sounds sensible; once the adapter has been disposed, it really shouldn't be usable anymore.

Although, I'm curious why this used to work in the past.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 31-Mar-2008 22:20:51   

It's likely that it's due to the optimization that's been added to the library: all fetches use string uniquing now, which means that if during a fetch of entities you have twice the string "Foo", you get one "Foo" instance and 2 references to it instead of twice the string "Foo" in memory. It saves memory simple_smile

This cache is cleared during dispose.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 03-Apr-2008 10:07:53   

I've added a check to Openconnection, where it throws an ObjectDisposedException if the adapter was already disposed.

Frans Bouma | Lead developer LLBLGen Pro