標籤:
前段時間試著用Entity Framework for Sqlite環境,發現了一些坑坑窪窪,記錄一下。
同時試了一下配置多種資料庫,包括Sqlite、Sql Server、Sql Server LocalDB、Sql Server Compact。
我建的demo項目結構以及通過NuGet安裝的包:
EFDemo.MultipleDB.UI引用了EFDemo.MutipleDB項目。
1. 遇到的異常1
The Entity Framework provider type ‘System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6‘ registered in the application config file for the ADO.NET provider with invariant name ‘System.Data.SQLite.EF6‘ could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
我是是引用了Sqlite相關的dll了的(見),但是發現產生後再EFDemo.MultipleDB.UI下的組建檔案中沒有自動將這些dll拷貝過來。
2.
於是我將這些手動拷貝過來了。
2. 遇到的異常2
剛才的異常沒了,又出現了一個異常。
The Entity Framework provider type ‘System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer‘ registered in the application config file for the ADO.NET provider with invariant name ‘System.Data.SqlClient‘ could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
這次在代碼裡面加了這麼一段,不用調用,只是在代碼裡讓它存在:
/// <summary> /// 解決provider不能自動載入的問題 /// (不需要調用,放在這裡即可) /// </summary> private static void FixProvidersNotAutoLoadProblem() { var _ = typeof(System.Data.SQLite.EF6.SQLiteProviderFactory); var __ = typeof(System.Data.Entity.SqlServer.SqlProviderServices); var ___ = typeof(System.Data.Entity.SqlServerCompact.SqlCeProviderServices); }
3. 遇到的異常3
使用了上面的方法,上面的那個異常沒了,又一個新的來了。
Unable to determine the provider name for provider factory of type ‘System.Data.SQLite.SQLiteFactory‘. Make sure that the ADO.NET provider is installed or registered in the application config.
Sqlite的那些包是通過NuGet安裝的,但是NuGet貌似沒有幫忙產生完整的配置,所以需要自己補上。
這裡貼上的是完整的,注意紅色的是添加的:
<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"/> <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" /> <remove invariant="System.Data.SqlServerCe.4.0" /> <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" /> </DbProviderFactories> </system.data> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework"> <parameters> <parameter value="System.Data.SqlServerCe.4.0" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" /> <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" /> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> <provider invariantName="System.Data.SqlServerCe.4.0" type="System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact" /> </providers> </entityFramework>
4. 雖然使用的是Code First,但是System.Data.SQLite.EF6是不能協助我們自動產生資料庫的表結構的,需要手動建立。(當然,可以找找有沒有其他支援Sqlite的Migration的EF Provider)
OK了,到此這幾個坑算是填平了。
5. 設定DataDirectory
我的Sqlite的連接字串是這樣寫的:
<add name="BloggingContext_SQLite" connectionString="Data Source=|DataDirectory|\Blogging_SQLite.db" providerName="System.Data.SQLite.EF6"/>
為了開發方便,我將資料庫檔案放在了項目裡面,這個樣子:
怎樣告訴連接字串DataDirectory在這裡呢?
private static void SetDataDir() { DirectoryInfo baseDir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); string data_dir = baseDir.FullName; if ((baseDir.Name.ToLower() == "debug" || baseDir.Name.ToLower() == "release") && (baseDir.Parent.Name.ToLower() == "bin")) { data_dir = Path.Combine(baseDir.Parent.Parent.FullName, "App_Data"); } AppDomain.CurrentDomain.SetData("DataDirectory", data_dir); }
在程式初始化時調用。
附:
完整代碼在這裡
Entity Framework使用Sqlite時的一些配置