System.Data.SQLite
View Ticket
Not logged in
Ticket UUID: a4e388829a24bec89984df0515161080724478a6
Title: EF6 Reload Method Fails using 1.0.96 with InvalidOperationException: "No current row"
Status: Closed Type: Code_Defect
Severity: Important Priority: Medium
Subsystem: None Resolution: Duplicate
Last Modified: 2015-04-24 00:23:29
Version Found In: 1.0.96
User Comments:
anonymous added on 2015-04-23 18:08:35: (text/x-fossil-plain)
Under System.Data.SQLite 1.0.96 use of the Entity Framework 6 Reload method on an Entry, or Refresh on an ObjectContext, will result in an InvalidOperationException, message "No current row".

The stack trace for this exception, included below, indicates that the exception is being thrown in the SQLiteDataReader.GetDataTypeName method. The call to VerifyForGet() is causing the problem as the SQLiteDataReader is not actually in a reading state at that point.

The SQLite team recently fixed a very similar issue that affected the GetOrdinal method under 1.0.95. This was reported under ticket c28d7fe915 (http://system.data.sqlite.org/index.html/tktview/c28d7fe915). The following commit fixed the issue: 

https://system.data.sqlite.org/index.html/fdiff?v1=3e4f8552d0ccc7b8&v2=49b118164e80e977&sbs=1).

This small patch against the System.Data.SQLite source tree resolves the issue in the same way by removing the call to VerifyForGet() from SQLiteDataReader.GetDataTypeName. It has been verified to fix the issue with EF6.

diff -crB original/System.Data.SQLite/SQLiteDataReader.cs new/System.Data.SQLite/SQLiteDataReader.cs
*** original/System.Data.SQLite/SQLiteDataReader.cs	Thu Apr 23 13:26:09 2015
--- new/System.Data.SQLite/SQLiteDataReader.cs	Thu Apr 23 13:28:13 2015
***************
*** 536,542 ****
      public override string GetDataTypeName(int i)
      {
          CheckDisposed();
-         VerifyForGet();
  
          if (i >= PrivateVisibleFieldCount && _keyInfo != null)
              return _keyInfo.GetDataTypeName(i - PrivateVisibleFieldCount);
--- 536,541 ----

Reproducing this issue is possible using the following statements, assuming that context is a DbContext and o is a object loaded via EF6:

	context.Entry(o).Reload();

Likewise, given a set of refreshableObjects, ObjectContext.Referesh will throw the same exception:

	((IObjectContextAdapter)context).ObjectContext.Refresh(RefreshMode.StoreWins, refreshableObjects);

For reference, the stack trace for the exception follows:

   at System.Data.SQLite.SQLiteDataReader.CheckValidRow()
   at System.Data.SQLite.SQLiteDataReader.VerifyForGet()
   at System.Data.SQLite.SQLiteDataReader.GetDataTypeName(Int32 i)
   at System.Data.Entity.Core.Objects.Internal.BufferedDataRecord.ReadMetadata(String providerManifestToken, DbProviderServices providerServices, DbDataReader reader)
   at System.Data.Entity.Core.Objects.Internal.ShapedBufferedDataRecord.Initialize(String providerManifestToken, DbProviderServices providerServices, DbDataReader reader, Type[] columnTypes, Boolean[] nullableColumns)
   at System.Data.Entity.Core.Objects.Internal.BufferedDataReader.Initialize(String providerManifestToken, DbProviderServices providerServices, Type[] columnTypes, Boolean[] nullableColumns)
   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass12.<BatchRefreshEntitiesByKey>b__11()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass12.<BatchRefreshEntitiesByKey>b__10()
   at System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectContext.BatchRefreshEntitiesByKey(RefreshMode refreshMode, Dictionary`2 trackedEntities, EntitySet targetSet, List`1 targetKeys, Int32 startFrom)
   at System.Data.Entity.Core.Objects.ObjectContext.RefreshEntities(RefreshMode refreshMode, IEnumerable collection)
   at System.Data.Entity.Core.Objects.ObjectContext.Refresh(RefreshMode refreshMode, Object entity)
   at System.Data.Entity.Internal.InternalEntityEntry.Reload()
   at System.Data.Entity.Infrastructure.DbEntityEntry`1.Reload()

mistachkin added on 2015-04-24 00:23:29: (text/x-fossil-plain)
This is a duplicate of ticket [94252b90591a3f7f95796aca0a44bd6fd9b8dd82].

The underlying issue has already been fixed on trunk.