在Pocket PC中使用Web Service串連資料庫

來源:互聯網
上載者:User
web|串連資料庫 在Pocket PC中使用Web Service串連資料庫
前言
微軟的移動開發人員大會在六月的北京舉行了,國內的行動裝置 App軟體雖然是剛剛起步,但是這個前景寬廣的領域已經受到越來越多軟體廠商的關注了。行動裝置上的商業應用儘管剛剛起步,但已經顯示出巨大的發展潛力。

在微軟移動開發挑戰賽中,我的作品《饕餮元年無線餐飲管理系統》獲得了商業應用的三等獎。為了實現Pocket PC與後台資料庫伺服器的串連,我的作品中使用了.Net CompactFramework和Web Service技術,我將核心部分的實現原理拿出來與大家分享。在本文中沒有涉及《饕餮元年》的代碼,我用另外一個程式“SQL查詢分析器”作為示範的範例。



在嵌入式資料庫領域,世界各大資料庫廠商都提供了自己的移動解決方案,比如微軟的SQL Server CE、Sybase的iAnywhere、IBM的DB2 Everyplace等。雖然各家廠商都提供了資料同步的解決方案,而且實現原理大同小異,但是,每種資料同步方案都針對自己的資料庫,不能相容其他的資料庫產品。

那麼有沒有什麼辦法,可以通過一種機制來訪問多種資料庫呢?微軟的Mobile 2003已經完全支援.net Compact Framework開發,而.net對Web Service提供了很好的支援,開發人員可以很容易的開發Web Service的服務程式和用戶端應用。

本文討論的是在Windows Mobile2003平台上通過Web Service來訪問多種資料庫的解決方案。這肯定不會是行動裝置訪問多種遠端資料庫的最優解,但我希望這是利用現有技術實現的比較優秀的解決方案。



系統需求:Visual Studio .NET 2003

Pocket PC 2003 模擬器

IIS 5.0



第一個Web Service
目前Web Service受到了廣泛的關注,主流的開發工具都為Web Service開發提供了很好的支援。我們在這裡使用Visual Studio . NET 2003來做一個簡單的Web Service執行個體,讓不瞭解Web Service開發的程式員更好的進入後續話題的討論。

我們首先來建立一個ASP.NET Web Service工程:開啟File菜單,選擇New,然後是Project。在New Project對話方塊中,Project Types選擇“Visual C# Projects”,Templates中選擇“ASP.NET Web Service”。Location中選擇你的Web Service的位置和名稱,由於我的機器上配置了IIS服務,所以我將Web Service直接部署在本機上。請見圖一。




ASP.NET Web Service工程和ASP.NET十分相似,只是分頁檔的副檔名為asmx,而不是aspx。接下來,我們要為Web Service 建立一個WebMethod。開啟Service1.asmx.cs檔案,在class Service1中添加兩個WebMethod:YourName和welcom,代碼如下(粗體字為添加的代碼):

namespace WebService1

{

public class Service1 : System.Web.Services.WebService

{

……

[WebMethod]

public string YourName()

{

return "My Name is wolf!我就是老狼!";

}

[WebMethod]

public string welcom(string yourname)

{

string str = yourname+",歡迎使用wolf的Web Service";

return str;

}

}

}







這裡需要提醒大家注意的是,每個WebMethod都必須是public的,而且需要在函數前





























加上[WebMethod]的聲明。YourName函數返回一個包含英文和中文的string對象,主要是想測試一下Web Service的字串能否在支援Unicode的WindowsCE平台上正常現實。Welcom函數增加了一個參數,目的也是為了測試Web Service和WindowsCE平台間是否存在字串不能正常顯示的問題。

然後我們選擇Debug菜單中的Start命令(或者按F5)運行這個Web Service,出現如下介面:(見圖二)




可以看到,我們剛才編寫的兩個函數的名稱被顯示了出來。大家可以點擊函數名稱,來查看WebMethod的SOAP和HTTP POST等資訊,還可以直接點擊Invoke按鈕,查看WebMethod返回的結果是否正確。



如果您的Web Service工作一切正常,接下來,我們建立一個Smart Device應用程式,在Pocket PC 2003環境下調用我們的Web Service。如果您對如何在Visual Studio .NET 2003下如何建立Smart Device應用程式還不是很瞭解,希望您參考下面的說明。

開啟一個新的VS.NET的IDE環境,開啟File菜單,選擇New,然後是Project。在New Project對話方塊中,Project Types選擇“Visual C# Projects”,Templates中選擇“Smart Device Application”,然後點擊OK。




在Smart Device Application Wizard對話方塊中,有兩個列表框。上邊一個列表框選擇程式的目標平台,根據你開發使用機器上所安裝的SDK的不同可以顯示出不同的選項。其中Pocket PC中包括Pocket PC 2002和Pocket PC 2003;Windows CE中包括其他支援.NET Compact Framework的WindowsCE平台。如果您安裝了SmartPhone的SDK,這裡也會顯示出SmartPhone的選項。

下面的對話方塊選擇的是所建立的應用程式類型,包括Windows應用程式、類庫、Non-graphical應用程式和空工程。這裡的選項根據您選擇平台的不同也會略有差異。還有一點需要說明的是,如果您安裝了Mobile Internet Toolkit,您也可以通過這個嚮導來建立目標平台為Mobile裝置的ASP.NET Web程式。

我們在這裡選擇“Pocket PC”和“Windows Application”,點擊OK。我們就可以開始移動開發之旅了。




我們先來看一下IDE環境的全景:其實和WinForm程式的開發環境差不多吧。但請大家注意上圖中的下拉式功能表,做過WindowsCE開發的朋友們一定很熟悉吧。對了,這就是選擇應用程式輸出裝置的菜單。我們在這裡選擇“CHS Pocket PC 2003 – SDK Emulator”,我們可以選擇下拉式功能表旁邊的Connect To Device按鈕來啟動模擬器,也可以等到程式運行時再啟動模擬器。

請注意:Visual Studio .NET 2003會預設安裝Pocket PC 2002的SDK,您需要另外安裝Pocket PC 2003 SDK和中文映像才能夠看到這一項。不過您在Pocket PC 2002的模擬器下調試下面的應用程式也是沒有問題的。



下面,我們來添加Web References,選擇Project菜單下的“Add Web References”,或者在Solution Explorer中右擊Web References,在快顯功能表中選擇“Add Web References”。我們就會看到下面的對話方塊:




在URL裡要填寫Web Service的URL,還記得我們運行Web Service時IE地址欄中的URL嗎?http://localhost/WebService1/Service1.asmx。對嗎?如果是WinForm程式,這樣寫是正確的,但在Smart Device應用程式中,這樣寫就是錯的。請大家注意,下面討論的話題十分重要:Windows CE裝置的模擬器儘管運行在你的PC上,但它實際上是作為一台遠程裝置串連到你的PC上的。所以,如果寫“localhost”或者“127.0.0.1”,那麼程式訪問的將是模擬器,而不是你用來開發的PC機。所以,在這裡你必須填寫你的PC在網路中的實際機器名或者IP地址。所以這裡應該填寫http://yourname/WebService1/Service1.asmx(yourname表示你實際的機器名)。這裡如果您填寫的是localhost,開發環境也將為你找到Web References,但在調用Web Service時將出現異常。好了,填寫好URL,按GO按鈕,如果URL正確,則會顯示上圖的資訊,然後點擊Add References按鈕。這樣我們就可以在項目中使用這個Web Service了。

我們開啟介面編輯器,添加兩個Button和一個TextBox,用來調用兩個WebMethod。代碼如下:

private void button1_Click(object sender, System.EventArgs e)

{

yourname.Service1 myService = new yourname.Service1();

label1.Text = myService.YourName();

MessageBox.Show(myService.YourName());

}



private void button2_Click(object sender, System.EventArgs e)

{

yourname.Service1 myService = new yourname.Service1();

MessageBox.Show(myService.welcom(textBox1.Text));

}




yourname是Web Service的名稱,相當於命名空間,所以我們必須建立一個yourname中的Service1類的對象,然後調用Service1中的方法。大家可以看到,在C#程式中調用Web Server的方法和建立本地類並調用其方法的過程是十分類似的。另外需要說明的是,由於網路因素的影響,調用Web Service不一定成功,所以在商業軟體的開發中需要加入異常處理的代碼,這裡為了程式的簡潔就省略了。程式運行結果如下:






SQL查詢分析器
在瞭解了基本的Web Service的開發與調用之後,我們可以進入核心內容的討論了。Web Service是基於XML語言的,正是這種特性才使Web Service成為串連各種異構系統之間的橋樑。那麼有沒有一種可以在跨越不同資料庫來傳遞資料的簡單方式呢?ASP.NET Web Service是支援返回DataSet對象的,而DataSet又能夠被各種資料表示控制項所支援,比如DataGrid等,DataSet就是我們要找的橋樑。

在這一部分裡,我將建立一個SQL的查詢分析器,與其他查詢分析器不同的是,我可以在調用時再指定串連的資料庫類型,這樣就可以實現串連不同資料庫了。我們首先來建立SQL查詢分析器的Web Service部分:






先來看一下SQL Service的UML圖。我們沿用了上面SQL Service中的Service1類,並為它添加了五個WebMethod,其名稱和功能介紹見下表:

名稱
功能

SetDatabaseType
設定串連資料庫的類型

SetDbConnectionString
設定資料庫的連接字串

Create
建立資料庫操作對象

ExecuteNonQuery
執行不返回結果的SQL語句

ExecuteDataSet
執行SQL語句,並返回一個DataSet




在Web Service的Service1類中,我們首先來聲明三個變數用來分別儲存資料庫操作對象、資料庫連接字串和資料庫類型。注意,我們將變數聲明為static,是為了讓用戶端執行不同的WebMethod時,可以訪問到相同的資料庫操作對象和字串對象。DBOperater是資料庫操作類的基類,而等一下我們建立的是DBOperater衍生類別的執行個體。

private static DBOperater m_dbOperater;

private static string m_DatabaseType;

private static string m_DbConnectionString;



SetDatabaseType和SetDbConnectionString兩個WebMethod是為了設定資料庫類型和資料庫連接字串而提供的方法。在這裡需要特別提醒的是,將資料庫的連接字串作為Web Service參數,以明文的方式在網路上傳遞是一種十分危險的做法,這裡只是為了樣本程式的簡單才這樣實現的。強烈建議讀者在實現自己的Web Service時,用更好的方法來保護自己的資料庫連接字串。

[WebMethod]

public bool SetDatabaseType(string DatabaseType)

{

if(DatabaseType == "")

return false;



m_DatabaseType = DatabaseType;

return true;

}

[WebMethod]

public bool SetDbConnectionString(string DbString)

{

if(DbString == "")

return false;



m_DbConnectionString = DbString;

return true;

}

下面的Create方法,用來根據m_DatabaseType來建立相應的DBOperater衍生類別的對象。這裡需要說明的是,設定資料庫類型(SetDatabaseType)用的是string作為參數,而沒有使用enum類型或者其他類型,是為了再以後添加對新的資料庫支援時不必修改已有的用戶端原始碼。

[WebMethod]

public bool Create()

{

if(m_DatabaseType == "SQL Server")

{

m_dbOperater = new DBSqlServerOperater(m_DbConnectionString);

return true;

}

if(m_DatabaseType == "Access")

{

m_dbOperater = new DBAccessOperater(m_DbConnectionString);

return true;

}

return false;

}

而剩下的兩個WebMethod只是簡單的調用了DBOperater衍生類別對象的相應方法,而實際的資料庫操作則是在DBOperater衍生類別中具體實現的。這樣可以更好地實現資料庫操作與用戶端操作的分離。

[WebMethod]

public bool ExecuteNonQuery(string sql)

{

return m_dbOperater.ExecuteNonQuery(sql);

}

[WebMethod]

public DataSet ExecuteDataSet(string sql)

{

return m_dbOperater.ExecuteDataSet(sql);

}



我們將對資料庫操作的具體方法封裝到了DBOperater類中,並由DBOperater類派生出了DBSqlServerOperater和DBAccessOperater類,分別用來進行對Sql Server資料庫和Access資料庫的操作。DBOperater類暴露了兩個虛方法:ExecuteNonQuery()和ExecuteDataSet(),由衍生類別負責重載實現。而衍生類別也各自暴露了自己的建構函式,用來擷取串連資料庫字串。

下面是DBOperater類的實現代碼,可以看到DBOperater類中的兩個方法使用了virtual的關鍵字,聲明為虛函數。

// 資料庫操作基類

public class DBOperater

{

public virtual bool ExecuteNonQuery(string sql)

{

return true;

}



public virtual DataSet ExecuteDataSet(string sql)

{

return null;

}

}




在Web Service的體繫結構中,真正進行資料庫操作的只有DBOperater的衍生類別,我們下面看到的DBSqlServerOperater類,使用了System.Data.SqlClient命名空間中的資料庫操作類,對SQL Server資料庫進行儲存操作。DBAccessOperater類對OleDB資料進行操作,使用了System.Data.Oledb命名空間中的類。

// SQL Server 操作類

public class DBSqlServerOperater : DBOperater

{

public DBSqlServerOperater(string DBConnectionString)

{

m_SqlConnection = new SqlConnection(DBConnectionString);

}



public override bool ExecuteNonQuery(string sql)

{

if(sql == "")

return false;



m_SqlConnection.Open();



SqlCommand command = m_SqlConnection.CreateCommand();

command.CommandText = sql;



command.ExecuteNonQuery();



m_SqlConnection.Close();

return true;

}



public override DataSet ExecuteDataSet(string sql)

{

if(sql == "")

return null;



m_SqlConnection.Open();



SqlDataAdapter da = new SqlDataAdapter(sql,m_SqlConnection);



DataSet ds = new DataSet();

da.Fill(ds);



m_SqlConnection.Close();

return ds;

}



private SqlConnection m_SqlConnection;

}



// OleDb 操作類

……


這裡省略了與SQL Server操作類基本相同的Access操作類代碼。關於C#中重載和繼承的實現方式和注意事項,請參閱相關書籍。



由於對資料庫的操作已經在Web Service端做了封裝,所以用戶端的代碼實現起來就相對簡單了。SmartSQLClient包含兩個屬性頁面,第一個屬性頁面為Setting,設定須查詢的資料庫類型和資料庫連接字串,設定完畢後,點擊Setting按鈕,程式會將資料庫類型和連接字串儲存起來,並自動切換到第二個屬性頁面中。


第二個屬性頁面Query,包括一個textBox,用來書寫SQL查詢語句,一個DataGrid,用來顯示Web Service傳來的資料庫,兩個Button分別執行返回DataSet的SQL查詢和不返回結果集的操作。

現在我們來看一下ExecDataSet按鈕的響應函數,該函數首先建立一個Web Service訪問對象的執行個體,然後根據Setting中的設定,設定資料庫類型和資料庫連接字串,然後建立相應資料庫操作類的對象執行個體,並調用Web Service的ExecuteDataSet方法,將一個有效SQL查詢語句傳遞給Web Service,Web Service會返回一個DataSet對象,我們的用戶端程式會將DataSet中的第一個表顯示到DataGrid控制項中。

private void ExecDsBtn_Click(object sender, System.EventArgs e)

{

wolf.Service1 service = new SQLSmartClient.wolf.Service1();

service.SetDatabaseType(m_DatabaseType);

service.SetDbConnectionString(m_connectionString);

service.Create();

DataSet ds = service.ExecuteDataSet(textBox1.Text);

dataGrid1.DataSource = ds.Tables[0];

}

好了,到這裡,我們已經實現了一個可以在PDA端操作遠程SQL Server和Access資料庫的SQL查詢分析器了。隨著.Net資料庫操作組件的日益豐富,您完全可以實現對Oracle、DB2等流行的關係型資料庫的支援,並在此基礎上,實現更多基於行動裝置的應用程式。

與SQL SERVER CE互動
我們上面實現的SQL查詢分析器的意義不僅在於可以在行動裝置上方便地對不同類型的資料庫進行檢索,而且這種Web Service的方式還有更現實的意義。

眾所周知,在Windows CE平台上主流的資料庫是SQL Server CE,SQL Server CE與伺服器交換資料的方式主要有兩種:Remote Data Access(RDA)和Replication。這兩種資料同步的方式,不但需要搭建專門的IIS環境,而且只能與SQL Server資料庫進行資料同步。這就大大增加了使用其他類型資料庫的系統整合商開發行動裝置應用程式的難度,同時也不利於Windows CE平台被更廣泛的領域所接受。

下面的時間,我將在上面Web Service的基礎上,示範如何利用Web Service實現SQL Server CE與Access之間的資料同步。當然,我的實現還無法達到RDA可以將表結構同步複製的功能。

為了完成這部分的代碼,我們在SQLSmartClient中再添加一個屬性頁面,命名為SQLServerCE。最上面的textBox和CreateDB按鈕是為了建立SQL Server CE資料庫和資料庫中的表所準備的,稍後我們將介紹他們的代碼實現。而下面的Fill按鈕完成的任務包括:將第二個textBox中的SQL語句提交給Web Service,由Web Service負責提供包含相應資料的DataSet。然後解析DataSet,在組合成相應的SQL語句,插入到SQL Server CE資料庫中。


我們先來介紹一下在.Net Compact Framework中對SQL Server CE的操作。在.Net CF中針對SQL Server CE的操作類全部在System.Data.SqlServerCe命名空間中,其中類的名稱與操作方式和.Net Framework中System.Data.SqlClient類似。我們先來看一下,如何建立SQL Server CE資料庫:

// 建立SQL Server CE資料庫

private void CreateDBBtn_Click(object sender, System.EventArgs e)

{

if (File.Exists ( DBNametextBox.Text) )

File.Delete ( DBNametextBox.Text);



string connString = "Data Source = "+ DBNametextBox.Text;



SqlCeEngine engine = new SqlCeEngine (connString);

engine.CreateDatabase();



// Create Table

SqlCeConnection conn = new SqlCeConnection(connString);

conn.Open();

SqlCeCommand command = conn.CreateCommand();

command.CommandText = "CREATE TABLE Human (ID int PRIMARY KEY, Name ntext,Age int ,Address ntext)";

command.ExecuteNonQuery();

conn.Close();



MessageBox.Show("資料庫建立成功");

}

在這段代碼中,我們首先檢查sdf檔案是否存在,如果存在則刪除已存在的資料庫檔案(副檔名sdf)。然後根據給出的sdf檔案名稱構造資料庫連接字串,建立SqlCeEngine對象,並調用SqlCeEngine的CreateDatabase方法建立資料庫。最後一部分的代碼使用SqlCeConnection和SqlCeCommand建立了名為Human的表。

好了,建立好SQL Server CE資料庫了,該將Web Service上的資料取下來了。我們來看Fill按鈕的實現代碼。

第一步是建立Web Service的訪問對象,向Web Service請求DataSet資料庫。不多做解釋了。

private void FillDsBtn_Click(object sender, System.EventArgs e)

{

// Get Web Service DataSet

wolf.Service1 service = new SQLSmartClient.wolf.Service1();

service.SetDatabaseType(m_DatabaseType);

service.SetDbConnectionString(m_connectionString);

service.Create();

DataSet ds = service.ExecuteDataSet(SqlTextBox.Text);



第二步,我們根據上面建立好的SQL Server CE資料庫,組成資料庫連接字串,並建立SqlCeConnection和SqlCeCommand對象,看起來很眼熟,不是嗎?

// Get Sql Server Ce Database DataSet

string connString = "Data Source = "+ DBNametextBox.Text;

SqlCeConnection conn = new SqlCeConnection(connString);

conn.Open();



SqlCeCommand command = conn.CreateCommand();



第三步,我們從DataSet的第一個DataTable對象中得到DataRow數組,如果DataRow的數量不小於1,則表示DataRow數組中有資料。我們通過C#語言的foreach關鍵字來迴圈得到每一個欄位的值,然後將其儲存到相應的string對象中去,再由這些string對象組成SQL語句。最後用SqlCeCommand對象來執行這些SQL語句。

// Build Sql Command

String sql,Id,Name,Age,Address;

DataRow[] currRows = ds.Tables[0].Select(null, null, DataViewRowState.CurrentRows);

if( currRows.Length < 1)

return;

foreach(DataRow myRow in currRows)

{

Id = myRow["id"].ToString();

Name = myRow["name"].ToString();

Age = myRow["age"].ToString();

Address = myRow["address"].ToString();



sql = "INSERT INTO Human (id,Name,Age,Address) VALUES ("+Id+",'"+Name+"',"+Age+",'"+Address+"')";



// Execute Sql Command

command.CommandText = sql;

command.ExecuteNonQuery();

}



conn.Close();

MessageBox.Show("轉換完成");

}

最後關閉SqlCeConnection的串連,整個資料同步過程完成。我們通過SQL Server CE內建的查詢分析器,查看一下同步過來的資料,和Access表中的完全相同。當然,我們也可以將SQL Server CE中的資料同步到遠端資料庫中去,這裡就不再重複實現了。



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

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

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