DbContext不会发布SQLite数据库

首先,这些是我的意图:

  1. 在SQLite上创建一个DbContext
  2. 读/写它
  3. 关闭背景
  4. 将文件移动到另一个位置

1-3点工作完美。 当我尝试移动数据库时,问题就开始了。 我得到一个错误说明:

'The process cannot access the file because it is being used by another process.' 

我该如何解决这个问题?

首先,我创建一个上下文。 我必须在几种方法中使用它,我不想在每次需要时创建它。 所以我将它存储为成员。

 _sqliteContext = new SqlLiteContext(sqliteContextName); 

然后我想访问一个名为sync的表并获取其最新条目。

 var sync = _sqliteContext.Syncs.OrderByDescending(s => s.Date); _lastSync = sync.Any() ? sync.First().Date : new DateTime(0); 

而已。 然后我关闭上下文。

 _sqliteContext.Dispose(); 

并尝试移动文件。

 File.Move(sqliteUploadLocation, sqliteDownloadLocation); 

这是我得到例外的地方。

当我用插入替换选择时,如下所示:

 var sync = new Sync { Id = Guid.NewGuid().ToString(), Date = DateTime.Now }; _sqliteContext.Syncs.Add(sync); _sqliteContext.SaveChanges(); 

这有效,我可以移动数据库。 任何想法为什么我的选择不释放锁定?

更新


 // Start synchronisation. new SyncManager(mssqlString, sqliteUploadLocation).Start(); // Move file from upload to download location. try { File.Move(sqliteUploadLocation, sqliteDownloadLocation); } catch (Exception ex) { Console.WriteLine("Moving failed!"); Console.WriteLine(ex.Message); } public void Start() { // Create connection string for the sqlite database. const string sqliteContextName = "SqLiteContext"; var sqliteConnStringSettings = new ConnectionStringSettings { Name = sqliteContextName, ConnectionString = "Data Source=" + _sqliteUploadLocation + ";Version=3;BinaryGUID=False;", ProviderName = "System.Data.SQLite" }; // Read configuration, delete available connection strings and add ours. var conf = ConfigurationManager.OpenMachineConfiguration(); var connStrings = conf.ConnectionStrings; connStrings.ConnectionStrings.Remove(sqliteContextName); connStrings.ConnectionStrings.Add(sqliteConnStringSettings); try { conf.Save(ConfigurationSaveMode.Minimal); } catch (Exception) { // Insufficient rights to save. return; } ConfigurationManager.RefreshSection("connectionStrings"); // Create connection to the sqlite database. _sqliteContext = new SqlLiteContext(sqliteContextName); // Create connection to the mssql database. _mssqlContext = new MsSqlContext(_mssqlConnString); // Read last sync date. var sync = _sqliteContext.Syncs.OrderByDescending(s => s.Date); _lastSync = sync.Any() ? sync.First().Date : new DateTime(0); // Synchronize tables. //SyncTablePerson(); //SyncTableAddressAllocation(); // Creates an entry for this synchronisation. CreateSyncEntry(); // Release resources. _sqliteContext.Dispose(); _mssqlContext.Dispose(); } private void CreateSyncEntry() { var sync = new Sync { Id = Guid.NewGuid().ToString(), Date = DateTime.Now }; _sqliteContext.Syncs.Add(sync); _sqliteContext.SaveChanges(); } 

更新2


 public class SqlLiteContext : Context { public DbSet Syncs { get; set; } public SqlLiteContext(string connectionString) : base(connectionString) { Database.SetInitializer(new NoOperationStrategy()); } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonConfig()); modelBuilder.Configurations.Add(new AddressAllocationConfig()); modelBuilder.Configurations.Add(new AddressConfig()); modelBuilder.Configurations.Add(new SyncConfig()); } } public class NoOperationStrategy : IDatabaseInitializer where T : DbContext { public void InitializeDatabase(T context) { } } public abstract class Context : DbContext { public DbSet Persons { get; set; } public DbSet AddressAllocations { get; set; } public DbSet
Addresses { get; set; } protected Context(string connectionString) : base(connectionString) { } }

使用重构


 using (var sqliteContext = new SqlLiteContext(_sqliteContextName)) { // Read last sync date. var sync = sqliteContext.Syncs.Select(s => s).OrderByDescending(s => s.Date); var lastSync = sync.Any() ? sync.First().Date : new DateTime(1900, 1, 1); using (var mssqlContext = new MsSqlContext(_mssqlConnString)) { SyncTablePerson(sqliteContext, mssqlContext, lastSync); SyncTableAddressAllocation(sqliteContext, mssqlContext, lastSync); // Save server changes. mssqlContext.SaveChanges(); } // Creates an entry for this synchronisation. sqliteContext.Syncs.Add(new Sync { Id = Guid.NewGuid().ToString(), Date = DateTime.Now }); // Save local changes. sqliteContext.SaveChanges(); } 

我找到了另一个有同样问题的话题。 在我重构了我的代码之后,我补充道

 GC.Collect(); 

这删除了文件锁,我可以移动文件。

请参阅: https : //stackoverflow.com/a/14151917/2462736

想到两件事:

  1. 确保Visual Studio未锁定数据库文件。 打开服务器资源管理器,如果存在与文件的连接,请确保将其关闭或完全删除。
  2. 连接池很可能是保持连接打开的原因。 禁用连接字符串中的池,如下所示:

数据源= e:\ mydb.db;版本= 3; Pooling = False ;

正如Matt指出的那样,你应该使用using语句而不是手动调用dispose。 这样,如果存在exception,则始终正确地释放资源。