2018年1月24日 星期三

【.NET Core】使用SQLite

使用版本:

  • Visual Studio 2017 ver: 15.5.1
  •  .NET Core 2.0
  •  System.Data.SQLite.Core ver: 1.0.106


參考資料:




1. 到官網下載SQLite (可省略)
  到這邊(不放心的可以到官網點Download)選已經build過的,或者取得原始碼再自己編譯
我比較懶又沒特別需求,打算再Window x64的環境跑,所以是選Download的「Precompiled Binaries for Windows」→「sqlite-dll-win64-x64-3220000.zip」

  如果打算用cmd去操作,還要可以下載「sqlite-tools-win32-x86-3220000」,這樣就能在cmd中透過指定建立db或進行管理,但是... 值在太辛苦了,所以靠第三方工具吧!


2. 下載第三方工具 (有其他管理工具也可省略)
  問了Google大神,他給我 DB Browser for SQLite ,就來試用看看了
總之,進入網頁後,在右邊找到我要的版本「Download 64-bit Window .exe」,下載後就一路下一步到底,然後執行(如果看到黑色的cmd閃出來又消失,是正常的別緊張)。

  它將sqlite3的指令都圖形化,上手並不難,如果已經有現成的DB就選「打開資料庫」,而我什麼都沒有,所以是選「新建資料庫」。點下去後它會彈出Dialog要選新增在哪個位置,打上檔名後「存檔」。

  接著試「編輯資料表定義」,它雖然有Advanced項目,但Rowid各人強烈建議要有,而我也不是建立Temp table,兩個都維持未勾選狀態就好。如果熟悉語法能直接在下面打,但要注意... SQL語法不完全相容喔!,避免敲錯字,我還是點「加入欄位」,接著試需求將「名稱、類型、非空(not null)、PK、AI(自動增值)、U(唯一值)、預設(Default)、檢查()、Foreign Key」設定完,就可以點「OK」。

    只是測試...我只建了三個欄位,自動產生的語法如下:
    CREATE TABLE `` (
     `id` INTEGER PRIMARY KEY AUTOINCREMENT,
     `name` TEXT NOT NULL,
     `comment` TEXT
    );

簡單說一下各頁籤用圖

  1. Database Structure: 想查Table屬性, 有哪些View(視圖), 異動Table都是在這
  2. Browse Data: 這是異動特定Table的內容,可以增減編輯Rows。「過濾」其實就類似『WHERE xxx LIKE '%ooo%'』;Table的下拉選單可以切換;要增加row就點「新建記錄」,反之則「刪除記錄」;要編輯資料就點一下那欄位後直接輸入。
  3. Edit Pragmas: 暫時用不到,所以pass
  4. Excute SQL: 直接使用SQL語法(大致上能用,但強烈建議參閱下方的連結),一樣能使用F5來Execute

最後當然少不了存檔!  雖然關閉時會跳提醒,問要不要儲存變更,但也能夠主動儲存的!
Write Changes: 寫入改變。會把寫在Memory中的資料(也就是未儲存的變更),寫到檔案中
Revert Change: 復原改變。放棄Memory中的資料(不儲存變更且恢復原狀),重讀檔案

2018/1/28: 不過Import和Export的方便性不夠,後來我又找了「SQLite Studio」來用

3. 正片終於開始的用C#存取 *.db

※強烈建議在NuGet中下載 System.Data.SQlite.Core 。因為用 Microsoft.Data.Sqlite 會非常的辛苦(DataTable無法簡單轉移,只有Reader沒有Adpater等,而且對IReader的支援性很差,會有Complier能過,實際執行卻會跳Exception的情況)


public IActionResult Index()
{
      //個人習慣會在一開始就開變數,可以無視
      string str = string.Empty;
      List _str = new List();

      //這裡才是SQLite重點
      //將Data Source指到檔案位置
      //用Directory.GetCurrentDirectory()可以簡易的取得根目錄
      string path = @"Data Source = "
            + Directory.GetCurrentDirectory()  
            + @"\Areas\Event\Data\TestBrowser.db"; 
      //進行連線,用using可以避免忘了釋放
      using (SQLiteConnection conn = new SQLiteConnection(path)) 
      {
          //再來這邊的步驟跟操作其他DB很像,就是建立Command,然後連入合法的SQL語句,再Open連線
          string sql = "select * from FastTest"; 
          SQLiteCommand cmd = new SQLiteCommand(sql,conn);
          conn.Open();

          //連線有Open後,就能用Reader去讀取Query結果
          SQLiteDataReader reader = cmd.ExecuteReader();

          //這是用Microsoft.Data.Sqlite時的寫法,只能這樣先推到儲存資料再另外處理。
          while (reader.Read())
          {
              _str.Add(reader["name"].ToString());
          }

          //改用System.Data.SQLite後,要轉DataTable只要用Load()就行了
          DataTable dt = new DataTable();
          dt.Load(reader);

          //如果是用adapter跟DataSet就更簡單了
          SQLiteDataAdapter adapter = new SQLiteDataAdapter(sql, conn); //似乎不能直接用cmd? 會有Exception
          DataSet ds = new DataSet();
          adapter.Fill(ds, "FirstTable"); //用 .Fill(ds) 就夠了,要重新命名TableName才需要放第二個參數
          //接著只要 ds.Tables[0] 就能取出DataTable (當然... DataSet不止能這樣用)
      }

      //這裡則是用來看接到哪些資料, reader示範, DataTable的部分預計要跟vue配合,那時再說 XD
      str = string.Join(", ", _str.ToArray());
      ViewBag.DBdata = str;
      return View();
}

這樣之前在 *.cshtml 中寫 @ViewBag.DBdata; 的位置,就會顯示SQLite中撈出來的結果了!


想把DB帶著走,去除微軟的Access,我只想到SQLite
與其說心得分享,更像是純日記
重0開始弄SQLite已經是第二次了,卻忘的一乾二淨,為了省掉不知哪時會遇到的第3次而留下的記錄,就直接記錄我的操作

由於可能會有多人線上操作(給管理者用,尖峰約3~7人),所以也查了一下這部分,SQLite似乎只有「寫入」的瞬間會Lock檔案(畢竟是以檔案的方式儲存),而官方說法是100K/每日的點擊量完全可以承受(資料如果不複雜,400K/日也能行),看起來應該勘用。現在我只擔心using的回收機制太慢,改天再試試看要主動Close,還是等using釋放資源。

如果有更好的選擇還請指點!

補充資料:
(英文)SQLite官網:https://sqlite.org
(英文)SQLite的型別及轉換參考:http://www.sqlite.org/datatype3.html
(簡中)菜鸟教程 - SQLite 数据类型 :http://www.runoob.com/sqlite/sqlite-data-types.html