目前,基于數(shù)據(jù)庫服務(wù)器的桌面管理程序和Web程序已經(jīng)有太多的應(yīng)用了,尤其是網(wǎng)絡(luò)的大量普及,孤立地?cái)?shù)據(jù)庫管理系統(tǒng)無法勝任分布式管理應(yīng)用,但是面對基于access數(shù)據(jù)庫的現(xiàn)有的桌面應(yīng)用我們也無法完全的摒棄。我們利用.Net 遠(yuǎn)程處理功能將連接和存取Access的行為封裝為一個(gè)遠(yuǎn)程對象,供網(wǎng)絡(luò)中其它客戶端通過調(diào)用該遠(yuǎn)程對象來存取實(shí)際的Access數(shù)據(jù)庫。我們以 C# 2005 為開發(fā)語言來實(shí)現(xiàn)上述功能。
一、 技術(shù)要點(diǎn)
我們都知道Windows應(yīng)用程序在運(yùn)行時(shí)會啟動一個(gè)進(jìn)程,其總包括若干線程,不同的進(jìn)程之間通信是開發(fā)分布式應(yīng)用程序所必需的,傳統(tǒng)上,這不僅需要深入了解通信流兩端上進(jìn)程的對象,而且還要深入了解低級別協(xié)議的宿主、應(yīng)用程序編程接口以及配置工具等。總之,它是一項(xiàng)需要大量專業(yè)知識和經(jīng)驗(yàn)的復(fù)雜任務(wù)。
幸好.Net為我們提供了遠(yuǎn)程處理功能,它所提供的通信方法可以快速而方便地完成上述建立通信的任務(wù)。因此,無論是需要快速開發(fā) Web 應(yīng)用程序,還是要花費(fèi)更多時(shí)間生成關(guān)鍵的企業(yè)范圍的應(yīng)用程序,.NET Framework 都會提供支持。通過 .NET 遠(yuǎn)程處理,客戶端應(yīng)用程序可以使用同一臺計(jì)算機(jī)或其網(wǎng)絡(luò)中其他任何可用的計(jì)算機(jī)上的其他進(jìn)程中的對象。
要使用 .NET 遠(yuǎn)程處理創(chuàng)建可以讓兩個(gè)對象跨越應(yīng)用程序直接通信的應(yīng)用程序,只需生成以下對象即可:
1、 可遠(yuǎn)程處理的對象。
2、 偵聽對該遠(yuǎn)程對象的請求的應(yīng)用程序即服務(wù)器程序。
3、 對該遠(yuǎn)程對象發(fā)出請求的客戶端應(yīng)用程序。
.Net下不同應(yīng)用程序中的對象的通信方式有兩種:一種是跨應(yīng)用程序域邊界傳輸對象副本,一種是使用代理交換消息。MarshalByRefObject 是通過使用代理交換消息來進(jìn)行通信的對象的基類。當(dāng)跨應(yīng)用程序使用遠(yuǎn)程對象時(shí),對象的基類必須是從 MarshalByRefObject 繼承。
二、 程序?qū)崿F(xiàn)
(1)我們先在VS的IDE中創(chuàng)建名為“TestRemoteAccess”的新的解決方案來容納前述用來實(shí)現(xiàn)遠(yuǎn)程處理的三個(gè)項(xiàng)目,首先向解決方案中添加名為“RemoteObject”的類庫,然后將默認(rèn)創(chuàng)建的類名更改為“CRemoteAccess”,并且繼承于“MarshalByRefObject”,代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace RemoteObject
{
public class CRemoteAccess : MarshalByRefObject
{}
}
我們需要在該對象內(nèi)創(chuàng)建用于連接和存取本地Access數(shù)據(jù)庫的所有函數(shù),供服務(wù)端客戶端程序同時(shí)調(diào)用。用于連接和存取Access數(shù)據(jù)庫的方法這里不再詳述,參看附件源碼。
首先所有需要向客戶端公開的函數(shù)其可見性都必須設(shè)為 public。變量m_ConnString需要設(shè)置為public static,目的是當(dāng)客戶端調(diào)用了SetRemoteAccessConnString后將數(shù)據(jù)庫連接字符串保存下來以備在本次連接期間始終能夠訪問,代碼如下:
……
public static string m_ConnString;
……
public void SetRemoteAccessConnString(string Connstr)
{
m_ConnString = Connstr;
}
……
成功連接了Access數(shù)據(jù)庫后我們需要返回?cái)?shù)據(jù)集給請求的客戶端進(jìn)行顯示和編輯,在遠(yuǎn)程對象中我們聲明了幾個(gè)相關(guān)函數(shù):
PRivate void LoadData(string SqlStr, string TableName)
public void SaveData(DataTable ClientDataTable)
public DataTable GetUserTable(string SqlStr, string TableName)
客戶端可以傳遞SQL查詢腳本通過調(diào)用 GetUserTable來獲取相關(guān)數(shù)據(jù)庫表的數(shù)據(jù),并返回一個(gè)DataTable,然后可以將該DataTable附值給DataGridView以便將數(shù)據(jù)顯示出來。GetUserTable通過調(diào)用私有的LoadData 函數(shù)來完成對數(shù)據(jù)的獲取。SaveData函數(shù)用于將編輯過的數(shù)據(jù)集保存回本地Access數(shù)據(jù)庫文件,代碼如下:
……
m_connection.Open();
m_adapter.Update(ClientDataTable);
……
(2)遠(yuǎn)程對象創(chuàng)建完成,我們需要創(chuàng)建用于偵聽該遠(yuǎn)程對象請求的服務(wù)端應(yīng)用程序。在“TestRemoteAccess”解決方案中新建一個(gè)Windows窗體項(xiàng)目名為:“TestServer”,從工具箱中拖拽下幾個(gè)組件,界面如下所示:
![]() |
| …… remotableObject = new RemoteObject.CRemoteAccess(); TcpChannel channel = new TcpChannel(8080); ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject.CRemoteAccess), "RithiaTestAccessServer", WellKnownObjectMode.Singleton); …… |
| …… ProviderStr = ProviderStrPart + txtAccessMdbFileName.Text + ";Jet OLEDB:Database PassWord=" + txtAccessPassword.Text; …… remotableObject.SetRemoteAccessConnString(ProviderStr); …… |
![]() |
| …… string RemoteURL; Host = txtHost.Text; Port = txtPort.Text; RemoteURL = "tcp://" + Host + ":" + Port + "/RithiaTestAccessServer"; try { TcpChannel chan = new TcpChannel(); ChannelServices.RegisterChannel(chan); remoteObject = (RemoteObject.CRemoteAccess)Activator.GetObject(typeof(RemoteObject.CRemoteAccess), RemoteURL); RemoteDataTable = new DataTable(); button3.Enabled = false; } catch (Exception E) { MessageBox.Show(E.Message.ToString()); } finally { } …… |
| …… RemoteDataTable = remoteObject.GetUserTable(txtSQL.Text, "Test"); dataGridView1.DataSource = RemoteDataTable; …… |
| …… remoteObject.SaveData(RemoteDataTable); …… |
新聞熱點(diǎn)
疑難解答
圖片精選