Windows Mobile下Native C++訪問SqlCe的封裝

來源:互聯網
上載者:User
文章目錄
  • 開啟關閉
  • 建立刪除
  • 增刪改操作
  • 交易處理
  • 查詢操作
背景

進行Windows Mobile的應用的開發,很多時候需要對資料庫進行訪問,儲存和讀取。可是微軟沒有為Native C++提供象ADO.NET下的封裝,所以我自己封裝了一個SqlCe訪問類。

簡述

本文講述在Windows Mobile和Wince下,Native C++訪問SqlCe的封裝類的實現。由於微軟沒有為C++提供像ADO.NET的封裝,為Native C++訪問SqlCe製造了一定的難度,因此對OleDB訪問SqlCe進行封裝,方便使用SQL語句對SqlCe進行操作。

SqlCe訪問技術概述ADO.NET

.NET Compact Framework逐漸成為Windows Mobile和Wince的開發的主流,微軟為CF.NET提供了ADO.NET訪問SqlCe,對SqlCe的訪問封裝在System.Data.SqlServerCe下,和其他資料庫(SQL Server, Oracle)訪問基本相容,但是不支援DbProviderFactory。例如下面的代碼不能通過編譯,因為沒有SqlCeProviderFactory類。

DbProviderFactory factory = SqlCeProviderFactory.Instance;

我之前封裝了一個ADO.NET的SqlCe訪問類,可以參考 .NET Compact Framework下SQL CE的使用 和 實現了SqlCeHepler的單元測試類見.NET Compact Framework下的單元測試。

OleDb

在Native的世界,可以通過OleDb來訪問SqlCe。OleDb封裝在sqlceoledb35.dll下,使用OleDb需要安裝一個Cab包如下:

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Devices\wce500\armv4i\sqlce.repl.ppc.wce5.armv4i.CAB

上述路徑根據平台有所不同。

注意上述sqlceoledb35.dll只是支援SqlCe 3.5,微軟對不同版本的SqlCe的相容性不是很好,可以參考 SQL Server Express和SQL Server Compact的應用 和 .NET Campact Framework下SQL CE相容性問題 瞭解SqlCe的曆史我相容性問題。

本文後續會重點講述OleDb。

ADO

在Windows Mobile和Wince平台,微軟官方不支援ADO。但是有一個社區實現,可以參考 A set of ADOCE classes。我沒有試過,所以不好評論。

 

實現

下面講述如何基於OleDb實現對SqlCe的訪問。

文檔和Samples

微軟提供了線上文檔,可以在 Microsoft SQL Server Compact 3.5 Books Online and Samples下載。上述連結只是包含線上文檔,沒有提供例子程式的,所以這個名字有點騙人感情之嫌。雖然提供了線上文檔,但是文檔的品質不高,有些細節沒講,例如調用ICommand::Execute的入口參數就沒有講,我做的時候只能自己試。

雖然上面的連結不提供Samples,但是我們還有另外一個方法取得Samples。在

C:\Program Files\Microsoft SQL Server 2005 Mobile Edition\Samples\NorthwindOleDb

下可以得到Sample代碼,前提是安裝了Microsoft SQL Server 2005 Mobile Edition。但是要注意不同SqlCe版本實現有所不同,這個代碼要結合上面的Online book修改才行。

基於SQL語句的實現

微軟的例子程式NorthwindOleDb提供了通過OleDb訪問SqlCe的方法,但是不提供對SQL語句的封裝,直接對錶的訪問效率比較高,但是也有很大的不便性。因為每個操作都單獨封裝一個函數,每個函數大概至少需要100行代碼,而且有指標等資源的分配,釋放等操作,一旦沒有處理好就發生記憶體流失了。所以我偏向於使用統一的SQL語句介面對SqlCe進行操作,雖然犧牲了點效能,卻提供了方便性。下面是目前的版本的封裝類。這個類是基於João Paulo Figueira 的OleDbClientLib3實現的。

開啟關閉
bool Open(const CString& dbPath);
void Close();

上面為開啟和關閉SqlCe資料庫連結的操作,這裡實現為長連結,也就是不調用Close()的話,資料庫的Session一直連結著,這樣的好處是縮短訪問時間。

建立刪除
bool CreateDatabase(const CString& dbPath);
bool DeleteDatabase(const CString& dbPath);

由於SqlCe是in-process資料庫,物理上表現為就一個檔案,可以方便建立和刪除,上述介面就是建立和刪除SqlCe資料庫,建立後自動開啟資料庫的Senssion了。

增刪改操作
int  ExecuteNonQuery(const CString& sql);

把增刪改的語句調用ExecuteNonQuery()執行就可以了。

SqlCeHelper db;
HRESULT hr = db.Open(DB_FILE_NAME);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

CString sqlStr;
for(int i=0; i<max; ++i)
{
SYSTEMTIME currentTime;
GetLocalTime(&currentTime);
sqlStr.Format(L"INSERT INTO T1 (F1, F2, F3) VALUES(%d, 'STR%d', '%d-%d-%d %d:%d:%d')",
i, i, currentTime.wYear, currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond);
hr = db.ExecuteNonQuery(sqlStr);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}
}

db.Close();

上面是一個Insert語句的例子。

 

交易處理
void BeginTransaction();
void CommitTransaction();
void RollbackTransaction();

但是目前的版本還沒有事務支援。

查詢操作

其實這麼多操作之中查詢操作的實現是最複雜的。

int     ExecuteReader(const CString& sql);

執行ExecuteReader()會根據select語句初始化一個結果集,和ADO.net的實現不一樣,這個結果集不是直接通過DataSet或者DataReader來返回的,而是保持在內部的IRowset的結構裡面。為了方便使用,SqlCeHelper實現了一個唯讀,向前的資料讀取方法。

bool IsEndOfRecordSet();
void MoveNext();
void CloseReader();

int GetRowInt(const long ordinal);
double GetRowDouble(const long ordinal);
CString GetRowStr(const long ordinal);

當調用ExecuteReader()後,可以調用IsEndOfRecordSet()判斷結果集是否為空白。MoveNext()為移動到下一條記錄。GetRowInt(), GetRowDouble()和 GetRowStr()為讀取目前記錄的資料。CloseReader()關閉結果集。

    SqlCeHelper db;
HRESULT hr = db.Open(DB_FILE_NAME);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

CString sqlStr;
sqlStr.Format(L"SELECT * FROM T1");
hr = db.ExecuteReader(sqlStr);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

while(!db.IsEndOfRecordSet())
{
wprintf(L"F1=[%d], F2=[%s], F3=[%s]\n", db.GetRowInt(1), db.GetRowStr(2), db.GetRowStr(3));
db.MoveNext();
}
db.CloseReader();
db.Close();

上面示範整個讀取過程。

Unit Test

項目開發中使用了TDD,關於Unit Test可以參考Wince和Windows Mobile下native C++的單元測試 和 Windows Mobile下使用CppUnitLite輸出測試結果 。

TO-DO-LIST

**Support to open the database with password

**Support to specify the Open Mode

**Support to load Ole Db without COM registry.

**Support Transactions

**Support Parameters

關於項目

我把項目host到codeplex了,項目首頁連結如下:

SqlCeHelper - Native C++ SQL Helper class for SQL Server Compact

檢查和下載最新版本連結如下

http://sqlcehelper.codeplex.com/SourceControl/ListDownloadableCommits.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.