Entity Framework - Entity Framework Code First with SQLite Database Engine

SQLite是一套SQL資料庫引擎,並不算一套資料庫。SQLite可以模擬出SQL資料庫的標準與Table, Trigger, View等,但它不像資料庫有獨立的Server Process監聽執行,儲存方式也只是針對一個Local Disk檔案進行存取,檔案格式沒有限定,副檔名可以任意命名,SQLite對開發人員可說是一個輕量型的資料儲存方式,當要開發一個小型輕量的APP時可以使用。SQLite著名的應用就是Android的內部資料庫。但這篇的重點是在於要如何使用Entity Framework Code First搭配SQLite。


首先在Local建立一個SQLite Database檔案,有兩種方式:
a. 直接產生(按右鍵新增檔案,在修改副檔名)



b. 使用資料庫管理系統產生






接著就可以使用資料庫管理系統開啟SQLite檔案進行Create Table...等操作(限量使用Navicat這套資料庫管理工具)。




好了,SQLite資料庫產生好了,再來要來使用EF來連SQLite。在下列範例中,限量使用ASP.NET MVC5專案引入EF6。

Step1.. 首先透過NuGet加入安裝SQLite相關套件。



搜尋SQLite,安裝最上面的套件(安裝上面第一個套件後會自動將下面兩個套件一起安裝)。

Step2. 加入EF6 Code First Model Code與DbContext Code。
UserInfo.cs


using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Web;

namespace PTMWeb.Models
{
    public partial class UserInfo
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Nickname { get; set; }
        public string Account { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string PhoneNum { get; set; }
    }

    public class UserInfoDBMapping : EntityTypeConfiguration<UserInfo>
    {
        public UserInfoDBMapping()
        {
            this.ToTable( "UserInfo" );
            this.HasKey( m => m.Id ).Property( m => m.Id ).HasColumnName( "Id" );
            this.Property( m => m.Name ).HasColumnName( "Name" );
            this.Property( m => m.Nickname ).HasColumnName( "Nickname" );
            this.Property( m => m.Account ).HasColumnName( "Account" );
            this.Property( m => m.Password ).HasColumnName( "Password" );
            this.Property( m => m.Email ).HasColumnName( "Email" );
            this.Property( m => m.PhoneNum ).HasColumnName( "PhoneNum" );
        }
    }
}

上述程式碼為一個使用者資訊的Model,利用UserInfoDbMapping的Class描述Model欄位與Db欄位的對應。

PTMContext.cs

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace PTMWeb.Models
{
    public class PTMContext : DbContext
    {
        public DbSet<UserInfo> Users { get; set; }

        public PTMContext()
        {
            Database.SetInitializer<PTMContext>( null );
        }

        protected override void OnModelCreating( DbModelBuilder modelBuilder )
        {
            modelBuilder.Configurations.Add( new UserInfoDBMapping() );
        }
    }
}

上述程式碼為連接DB的EF6 Code,透過在Controller宣告PTMContext Instance可以對DB進行IO動作。

這樣你以為就結束了嗎? 當你程式執行到DB IO動作時就會馬上跑出以下錯誤。

這個原因是因為.Net找不到System.Data.SQLite的Entity Framework Provider,而System.Data.SQLite的Entity Framework Provider是在Web.config裡定義,在安裝SQLite相關套件時,NuGet會自動在Web.config裡加上SQLite Entity Framework Provider,但自動加上的config字串有一點問題,只要按照下面修改部分修改就可以執行了。
Web.config修改部分


<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
        <parameters>
     <parameter value="v11.0" />
 </parameters>
    </defaultConnectionFactory>
    <providers>
 <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
   
 <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
 <!--增加下列-->
 <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
 </providers>
</entityFramework>

<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" />
    </DbProviderFactories>
</system.data>

<connectionStrings>
    <add name="PTMContext" connectionString="Data Source=|DataDirectory|PTMDB.db" providerName="System.Data.SQLite" />
</connectionStrings>

上面修改部分主要是複製原本自動加的System.Data.SQLite.EF6 Provider,把名稱改為System.Data.SQLite,因為.Net會去找System.Data.SQLite的Provider而不是System.Data.SQLite.EF6。

上面限量的方法只是其中一種解決方式,網路上有其他解決方式,像修改connectionStrings裡的providerName與DbProviderFactories的System.Data.SQLite,限量是沒試過啦,總而言之,只要能順利連接就OK了。



留言