2015-09-22 116 views
4

我試圖使用實體框架6與SQLite和試圖使用TransactionScope運行到數據庫鎖定問題。這是我的代碼:TransactionScope和SQLite數據庫被鎖定

using (var txn = new TransactionScope()) 
{ 
    using (var ctx = new CalibreContext()) 
    { 
     var book = ctx.Books.First(x => x.Id == 2); 
     var author = ctx.Authors.First(x => x.Id == 3); 
     book.Authors.Add(author); 
     ctx.SaveChanges(); 
    } 
    txn.Complete(); 
} 

第一行var book = ctx.Books.First(x => x.Id == 2);執行正常。但是一旦我轉向下一個,我會收到一個異常,說我的數據庫已被鎖定。這是我的應用程序配置:

<configuration> 
    <configSections> 
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 
    </configSections> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /> 
    </startup> 
    <connectionStrings> 
    <add name="CalibreContext" connectionString="Data Source=metadata.db" providerName="System.Data.SQLite.EF6" /> 
    </connectionStrings> 
    <system.data> 
    <DbProviderFactories> 
     <remove invariant="System.Data.SQLite" /> 
     <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> 
     <remove invariant="System.Data.SQLite.EF6" /> 
     <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".Net Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> 
    </DbProviderFactories> 
    </system.data> 
    <entityFramework> 
    <defaultConnectionFactory type="Calibre.Dal.Ef.SQLiteConnectionFactory, Calibre.Dal.Ef" /> 
    <providers> 
     <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> 
     <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> 
    </providers> 
    </entityFramework> 
</configuration> 

我需要因爲除了執行數據庫操作使用TransactionScope,我也必須執行我打算加入到同一個交易(目前不存在)的文件系統操作。

回答

4

我遇到了類似的問題。只是要清楚,我在第二個查詢中遇到的錯誤是「底層提供程序在打開時失敗」(但是Open失敗的原因是數據庫被鎖定)。

顯然這個問題與MSDTC有關(TransactionScope與MSDTC緊密耦合)。

我發現a community addition to an MSDN page這反過來引用this blog post
......其中指出,交易是「提升」到MSDTC交易如果連接關閉並重新打開。哪些EF默認爲。通常這是一件好事 - 你不希望數據庫句柄永遠懸掛 - 但在這種情況下,行爲會阻礙。

解決的辦法是明確地打開數據庫連接:

using (var txn = new TransactionScope()) 
{ 
    using (var ctx = new CalibreContext()) 
    { 
     ctx.Connection.Open(); 
     // ... remainder as before ... 

或者,如果你所有的CalibreContext對象是短暫的,你可以想見,在打開的CalibreContext構造的連接。

這似乎解決了我的問題。如果我有任何其他報告,我會發布更新。