【物聯網智能網關-16】成功移植SQLite(STM32 .NET MF平臺)

 前言數據庫

.NET Micro Framework系統官方代碼是不支持任何數據庫的,這對一些具備用戶管理的Web Server、RFID數據採集和複雜的手持機應用來講是很是不方便的。多線程

很早就知道了SQLite,可是一直沒有深刻研究,隨着目前移植的.NET Micro Framework系統愈來愈成熟,用戶對數據庫支持的呼聲也愈來愈高,迫切須要一個數據庫平臺了。考慮到移植難度和代碼大小,最初原打算把YFIOs系統中的內存YFIODB數據庫修改成文件版本,這樣移植是最快的,代碼也比較小,可是缺點是比較明顯的,不支持Select等相關的SQL語句,這對熟悉數據庫應用的用戶來講,還須要從新瞭解數據庫的操做方法,還不如用文件來實現了。併發

在這個過程當中,也瞭解了其它的嵌入式數據庫,如FastDB、Berkeley DB等開源嵌入式數據庫,但其用戶羣和知名度遠比不上SQLite,考慮到物聯網中間件自己就是一個框架和平臺,供用戶二次開發,用戶越熟悉的技術就應該優先選擇。框架

肯定了要移植SQLite數據庫,可是又引出一個問題,是移植SQLite最新的版本?仍是之前相對代碼較小的版本?這着實讓我躊躇了良久。ide

SQLite V2xV3x比較函數

項目測試

V2.8.17編碼

V3.7.15spa

API接口個數.net

44

207

源文件個數

44

89

源代碼字節數

1.32M

4.0M

Win32 dll庫大小

209K

591K

文本編碼支持

UTF-8或iso8859

UTF-八、UTF-16

二進制數據(Blob)

不支持

支持

行編號

32字節

64字節

併發性

多讀,單寫

改良的併發性

.NET Micro Framework的核心代碼也不過300K左右,若是支持一個比本身核心還大的多的數據庫,真有點小馬拉大車的感受,因此在知足基本功能的基礎上(之前我比較擔憂V2x版本的國際化應用,好比是否支持中文),代碼大小是我最關注的。

在Windows平臺上對SQLite V2.8.17進行測試後,決定移植V2x版本的SQLite(固然後續不排除再移植3.0版本),移植成功後,release版本的 SQLite的大小大概130K左右。

SQLite V2xV3x .NET Framework開發

考慮到.NET Micro Framework是.NET框架,因此最初研究的是System.Data.SQLite.dll庫,後來發現,一是System.Data.SQLite.dll封裝的太過複雜,二是System.Data.SQLite.dll對.NET Framework的框架很是依賴,而且針對不一樣平臺,很難作到直接拷貝就可使用(必需要安裝),三是沒有支持SQLite V2x的版本。

因此最後仍是決定用Interop的方式直接訪問Win32 的 SQLite.dll。網上搜索了一下,有關於SQLite3的相關示例,SQLite V2x的就沒有了。因此先研究了一下SQLite3的接口應用,而後根據C++相關的接口定義,反推了一下SQLite V2x的C#接口。

在Windows .NET Framework平臺測試SQLite V2x接口(以下圖)沒有問題的狀況下,纔開始進行.NET Micro Framework 平臺下的SQLite V2x的移植。

 

SQLite V2x .NET Micro Framework移植

理論狀況下,只須要對OS.c代碼中的接口進行.NET MF的實現便可(標準的OS.c文件已經支持Windows,UNIX、Mac OS平臺)。但實際移植髮現,遠沒有這麼簡單。

(1)、SQLite代碼都是標準的C語言,可是OS.c中須要調用.NET MF自己的C++代碼操做接口,因此SQLite全部源碼的c擴展名一概修改成cpp接口,採用cpp編譯器進行編譯,可是這樣修改後,會出現不少編譯錯誤,大都是類型轉換的錯誤。

(2)、.NET Micro Framework平臺不支持(或不建議)直接採用標準的string.h、ctype.h、math.h和stdio.h等頭文件定義的函數。.NET Micro Framework代碼中已經有部分字符串操做的實現,可是爲了實現SQLite的正確編譯,還必須本身補全相關操做函數。時間、文件等操做函數,也須要轉換爲.NET Micro Framework平臺下的,或者本身實現。

(3)、內存分配相關函數.NET Micro Framework有兩類,一種就是private_開頭的函數,另外就是TinyCLR支持的內存操做函數,因爲兩者使用的堆空間不一樣(private_開頭的操做Custom_Heap,這個通常都比較小),因此我調試的時候採用private_開頭的函數,實際應用則是TinyCLR內存操做函數。把SQLite內存相關操做的函數,修改成.NET Micro Framework的。

(4)、因爲.NET Micro Framework底層代碼對文件的操做相對簡單,因此SQLite產生的臨時文件,我是在上層C#代碼中進行清除的。

(5)、鎖操做,.NET Micro Framework底層是沒法對文件進行鎖定操做的,考慮到.NET Micro Framework自己的特色(單進程,多線程),因此在上層C#代碼中進行了簡單的鎖實現(該鎖讀寫不能同時)。

(6)、SQLite指針應用的很是多,稍有不慎,系統就會出異常,因此在移植過程當中,必定要研究透各類接口指針的實際含義(好比定義char ***p這類指針,我之前就不多遇到) ,不然調試過程將是一個噩夢。

SQLite.NET MF應用開發

   .NET MF C#接口又進行了封裝,一是接口儘量和System.Data.SQLite.dll兼容,二是作一些必要的內存釋放和其它處理(如系統格式化,建立臨時目錄,磁盤刷新等等)。

   其實對相對簡單的嵌入式應用來講,數據庫無非就是建表,添加和修改數據,刪除,獲取表數據而已,而這些功能均可以經過SQL語句進行實現,因此說功能多,可是接口卻很簡單(以下圖所示)。

 

測試代碼以下:  

複製代碼
  public  static void Main()      {          string dbPath = "\\ROOT\\mftest.db";          using (SQLite db = new SQLite(dbPath)) //":memory:"))
         {              //建立表
             db.ExecuteNonQuery("CREATE TABLE student(id INTEGER, name VARCHAR(20), sex VARCHAR(2));");                 //插入數據
             db.ExecuteNonQuery("INSERT INTO student VALUES(1, '小紅', '女');");              db.ExecuteNonQuery("INSERT INTO student VALUES(2, '小李', '男');");              db.ExecuteNonQuery("INSERT INTO student VALUES(3, '小明', '男');");                 //讀取表
             YFDataTable table = db.ExecuteQuery("SELECT * FROM student"); // WHERE name = '小李';");

            string info = "";              foreach (YFColumn col in table.Columns)              {                  info += col.Name + " ";              }              Debug.Print(info);              foreach (YFDataRow row in table.Rows)              {                  Debug.Print(row[0].ToString() + "," + row[1] + "," + row[2]);              }          }          Thread.Sleep(Timeout.Infinite);      }
複製代碼

運行調試的場景以下圖所示:

 

 ----------------------------------------------------------------------

 

 

MF簡介:http://blog.csdn.net/yefanqiu/article/details/5711770

MF資料:http://www.sky-walker.com.cn/News.asp?Id=25

相關硬件: http://www.sky-walker.com.cn/Products.asp?Id=24

 

相關文章
相關標籤/搜索