Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating to EF 6.2.0 from EF 6.1.3 causes cannot access a disposed object error

I'm working with SQLite. I am able to use entity framework 6.1.3 in my WPF application without problems, but when I update it to 6.2.0 I get the following error:

Test method DataAccessLayerTests.GenericDataRepositoryTests.CRUD_On_Pipe threw exception: 
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SQLiteConnection'.
    at System.Data.SQLite.SQLiteConnection.CheckDisposed()
   at System.Data.SQLite.SQLiteConnection.get_State()
   at System.Data.Entity.Internal.RepositoryBase.CreateConnection()
   at System.Data.Entity.Migrations.History.HistoryRepository.QueryExists(String contextKey)
   at System.Data.Entity.Migrations.History.HistoryRepository.Exists(String contextKey)
   at System.Data.Entity.Migrations.History.HistoryRepository.GetPendingMigrations(IEnumerable`1 localMigrations)
   at System.Data.Entity.Migrations.DbMigrator.GetPendingMigrations()
   at Core.DatabaseContext.CreateAndSeedIfNotExists`1.InitializeDatabase(T context) in C:\Users\roadrunner\propulsimcs\Propulsim\Core\DatabaseContext.cs:line 40
   at System.Data.Entity.Internal.InternalContext.<>c__DisplayClassf`1.<CreateInitializationAction>b__e()
   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
   at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c)
   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Database.Initialize(Boolean force)
   at Core.DatabaseContext..ctor() in C:\Users\roadrunner\propulsimcs\Propulsim\Core\DatabaseContext.cs:line 114
   at DataAccessLayer.GenericDataRepository`1.GetAll(Expression`1[] navigationProperties) in C:\Users\roadrunner\propulsimcs\Propulsim\DataAccessLayer\GenericDataRepository.cs:line 16
   at DataAccessLayerTests.GenericDataRepositoryTests.CRUD_On_Pipe() in C:\Users\roadrunner\propulsimcs\Propulsim\DataAccessLayerTests\GenericDataRepositoryTests.cs:line 34




Debug Trace:
Native library pre-loader is trying to load native SQLite library "C:\Users\roadrunner\propulsimcs\Propulsim\DataAccessLayerTests\bin\Debug\x86\SQLite.Interop.dll"...

Any ideas?

like image 228
ferit Avatar asked Nov 16 '17 12:11

ferit


1 Answers

The problem is caused by a change in RepositoryBase class and incorrect (IMO) implementation of IDbConnection.State property by SQLiteConnection class (throwing ObjectDisposedException instead of returning ConnectionState.Closed when called on disposed object).

It's the same as reported in #398: NullReferenceException on Code First Migrations when Glimpse is installed. According to the status, it's already fixed in the EF6 repository, but unfortunately they decided to not provide patch, so you have to wait for v6.3. I've already reported the SQLite problem linking to this post, so hopefully they can change their mind.

Another option is to report the issue to SQLite development and wait a fix from there. In both cases, you have to wait for a fix in either SQLite or EF6 side. Note that the issue is reproducible even with the standard MigrateDatabaseToLatestVersion initializer.

I was able to workaround it by using the following ugly reflection hack:

public override void InitializeDatabase(T context)
{
    base.InitializeDatabase(context);

    var _historyRepository = migrator.GetType().GetField("_historyRepository", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(migrator);
    var _existingConnection = _historyRepository.GetType().BaseType.GetField("_existingConnection", BindingFlags.Instance | BindingFlags.NonPublic);
    _existingConnection.SetValue(_historyRepository, null);

    var x = migrator.GetPendingMigrations();
    if (x.Any())
    {
        migrator.Update();
        Seed(context);
    }
}

The original exception is gone, but now I'm getting another one saying 'No MigrationSqlGenerator found for provider 'System.Data.SQLite'. Use the SetSqlGenerator method in the target migrations configuration class to register additional SQL generators.' which I think is a different issue related to lack of MigrationSqlGenerator in SQLite EF services. It might or might not be a problem depending how did you solve that in 6.1.3.

Anyway, I would not recommend using the above hack. Either wait fox fix or downgrade to 6.1.3 for now.

like image 77
Ivan Stoev Avatar answered Oct 03 '22 09:10

Ivan Stoev