首先,客戶端通過remoting,訪問通道以獲得服務端對象,再通過代理解析為客戶端對象。這就提供一種可能性,即以服務的方式來發布服務器對象。遠程對象代碼可以運行在服務器上(如服務器激活的對象和客戶端激活的對象),然后客戶端再通過remoting連接服務器,獲得該服務對象并通過序列化在客戶端運行。
    在remoting中,對于要傳遞的對象,設計者除了需要了解通道的類型和端口號之外,無需再了解數據包的格式。但必須注意的是,客戶端在獲取服務器端對象時,并不是獲得實際的服務端對象,而是獲得它的引用。這既保證了客戶端和服務器端有關對象的松散耦合,同時也優化了通信的性能。
分布式數據庫系統
     就其本質而言,分布式數據庫系統的數據在邏輯上是統一的,而在物理上卻是分散的。與集中式數據庫相比它有如下主要優點:
  · 解決組織機構分散而數據需要相互聯系的問題。
  · 均衡負載。負載在各處理機間分擔,可避免臨界瓶頸。
· 可靠性高。數據分布在不同場地,且存有多個副本,即使個別場地發生故障,不致引起整個系統的癱瘓。
  · 可擴充性好。當需要增加新的相對自主的組織單位時,可在對當前機構影響最小的情況下進行擴充。
     ado.net
  分布式數據庫系統雖然有諸多優點,但它同時也帶來了許多新問題。如:數據一致性問題、數據遠程傳遞的實現、通信開銷的降低等,這使得分布式數據庫系統的開發變得較為復雜。幸運的是,微軟的.net開發環境為我們提供了c#開發語言和ado.net數據訪問模型,結合兩者來開發分布式數據庫系統能夠大大簡化開發工作。
    ado.net以xml為核心,是.net數據庫應用程序的解決方案。它使用離線數據結構,數據源中的數據被緩存到數據集(dataset)對象中,用戶無須鎖定數據源,數據以xml格式保存。在分布式數據庫系統中,很可能出現多個用戶同時訪問和修改數據的情況,因此,對于分布式數據庫系統,數據一致性是不可或缺的。ado.net通過使用樂觀一致性方案來控制數據一致性(實際上dataset對象被設計成支持使用樂觀一致性控制機制),即數據行只有在數據庫中真正被更新時才會被鎖定,而在悲觀一致性方案中,數據行在從被提取出來到在數據庫中更
新這段時間內一直被鎖定。因此,使用ado.net能夠在更少的時間內響應數量巨大的用戶。
  另外,在分布式數據庫系統中,還會經常遇到當用戶修改自從提取出來以來已經被修改的行時,違反一致性原則。對此問題ado.net也作了很好地解決,即使用dataset對象為每一條修改過的記錄維護兩個版本:原始版本和更新版本,在更新的記錄被寫回數據庫之前,先要把數據集中記錄的原始版本與數據庫中的當前版本進行比較,如果兩個版本匹配,就在數據庫中更新記錄;否則,就會出現違反一致性原則的錯誤。
    下面開始程序實現。 
第1章 系統總體結構 
1.1 總體結構圖 系統實現需要部署服務器端的遠程對象(即一個dbserverlibrary.dll),服務器端要注冊通道和該遠程對象。客戶端要實現一個本地查詢的服務器,同時根據sql解析的結果向各個服務器發送命令,并將結果顯示在客戶端界面,服務器端可以接受并顯示相應的命令。
1.2 關鍵組件結構圖
系統結構中關鍵的組件有遠程對象,和本地服務器,實現的功能基本一致。下面以遠程
對象為例,說明組件的實現。遠程對象在服務器端解決方案下的庫文件中聲明,通過服務器端進行注冊,客戶端通過tcp通道與服務器端遠程對象通信,實現數據集的查詢和傳輸。主要的數據成員有:sqlconnection(sql server數據庫的連接對象)、 sqlcommand (sql命令對象)、sqldataadapter(數據適配器,填充數據集)組件——dbserverlibrary:
 
第2 章 數據字典結構
因時間倉促,未實現數據字典,所有實驗要求的sql經過解析后,直接通過代碼判斷,
向相應場地發送命令。
第3 章 代碼結構
代碼分為三部分:遠程對象,服務器端代碼和客戶端代碼。
其中:遠程對象部署在各個服務器端,客戶端除了實現查詢命令的解析和傳送外
外,還有一個本地服務器,進行相應的本地查詢。
遠程對象代碼:
using system;
using system.runtime.serialization;
using system.data;
using system.data.sqlclient;
using system.windows.forms;
namespace dbserverlibrary
{
[serializableattribute] //it is very important for remoting data
public class dbserver : marshalbyrefobject
{
private string connstr;
private string clientsql;
public sqlconnection sqlconn;
public sqlcommand sqlcomm;
public sqldataadapter sqladapter;
public void getclientsql(string sql)
{
if(clientsql != null)
{
clientsql = null;
}
clientsql = sql;
messagebox.show(clientsql);
}
public dbserver()
{
//localdata initialize
connstr = "data source = localhost;initial catalog=ddb;user id=sa;password=;";
sqlconn = new sqlconnection(connstr);
}
public dataset getdataset() // 執行select
{
dataset ds = new dataset();
if (sqlcomm != null)
{
sqlcomm = null;
}
if(sqlconn.state == connectionstate.closed)
{
sqlconn.open();
}
try
{
sqlcomm = new sqlcommand();
sqlcomm.connection = sqlconn;
sqlcomm.commandtext = clientsql;
sqlcomm.commandtype = commandtype.text;
sqladapter = new sqldataadapter();
sqladapter.selectcommand = sqlcomm;
sqladapter.fill(ds);
}
catch(sqlexception ex)
{
messagebox.show(ex.message);
}
return ds;
}
public int executesql() //執行insert和delete
{
int affectednumber;
if (sqlcomm != null)
{
sqlcomm = null;
}
if(sqlconn.state == connectionstate.closed)
{
sqlconn.open();
}
try
{
sqlcomm = new sqlcommand();
sqlcomm.connection = sqlconn;
sqlcomm.commandtype = commandtype.text;
sqlcomm.commandtext = clientsql;
affectednumber = sqlcomm.executenonquery();
return affectednumber;
}
catch(sqlexception ex)
{
messagebox.show(ex.message);
return 0;
}
}
}
}
服務器端代碼:
private void frmsupplierserver_load(object sender, system.eventargs e)
{
tcpchannel chan = new tcpchannel(8888);
channelservices.registerchannel(chan);
//注冊提供服務的遠程對象 remotingconfiguration.registerwellknownservicetype(typeof(dbserverlibrary.dbserver) ,"dbserver",wellknownobjectmode.singleton);
}
客戶端代碼:
解析sql:sqlparse.cs
namespace supplierclient
{
public class sqlparse
{
//得到sql語句的類型
public string getsqltype(string sqltext) //type of sql statements
{
}
//得到select語句要查詢的表名
public string getselecttablename(string sqltext)
{
}
//得到select語句中的where子句
public string getwhereclause(string sqltext)
{
}
//得到查詢條件中的字段名
public string getselectfield(string sqltext)
{
}
//得到分片依據,返回scity的值
public string getselectcityvalue(string sqltext)
{
}
//設定select語句經解析后的格式
public arraylist setselectlist(string sqltext)
{
}
//如果沒有分片信息,則向3個場地都發送命令
public arraylist sendtoallsite(string sqltext)
{
}
//得到insert語句要查詢的表名
public string getinserttablename(string sqltext)
{
}
//根據插入的表和值,設定場地:insert into supplier values('no','name','city'),return city
public string getinsertcityvalue(string sqltext)
{
}
//如果表名是supplier,則根據city值設定向哪個場地發送命令
public arraylist setinsertsite(string sqltext)
{
}
//生成解析后的insert命令列表
public arraylist setinsertlist(string sqltext)
{
}
本地服務器查詢代碼:localserver.cs
namespace supplierclient
{
public class localserver
{
}
//返回查詢結果
public dataset makedataset(string sqltext)
{
}
//執行插入和刪除操作,并返回影響記錄數
public int executesql(string sqltext)
{
}
第4 章 界面
4.1 客戶端
客戶端啟動后,用戶首先在文本框中輸入sql命令,然后通過解析后向相應場地發送命令,并將返回的結果集進行合并,顯示在界面中,顯示結果后空白的文本框用來顯示執行插入刪除操作時的結果信息。
4.2 服務器
服務器端僅實現對遠程對象的注冊,因此界面不需要實現功能,只需要在啟動時注冊遠程對象即可,接收到的客戶端的用戶命令是通過消息框顯示的。如上圖所示。
第5 章 命令處理及核心算法流程
insert 操作——
//得到insert語句要查詢的表名
public string getinserttablename(string sqltext)
{
}
//根據插入的表和值,設定場地:insert into supplier values('no','name','city'),return city
public string getinsertcityvalue(string sqltext)
{
}
//如果表名是supplier,則根據city值設定向哪個場地發送命令
public arraylist setinsertsite(string sqltext)
{
}
//生成解析后的insert命令列表
public arraylist setinsertlist(string sqltext)
{
}
delete 操作——
向各個場地發送,通過定義數據庫中表的關系及約束來保證完整性和一致性,如果刪除命令不成功,則返回異常信息,否則,返回各個場地成功執行命令影響的記錄數目。
select 操作——
//得到sql語句的類型
public string getsqltype(string sqltext) //type of sql statements
{
}
//得到select語句要查詢的表名
public string getselecttablename(string sqltext)
{
}
//得到select語句中的where子句
public string getwhereclause(string sqltext)
{
}
//得到查詢條件中的字段名
public string getselectfield(string sqltext)
{
}
//得到分片依據,返回scity的值
public string getselectcityvalue(string sqltext)
{
}
//設定select語句經解析后的格式
public arraylist setselectlist(string sqltext)
{
}
//如果沒有分片信息,則向3個場地都發送命令
public arraylist sendtoallsite(string sqltext)
{
}
第6章 結論
遠程處理是.net框架提供的一項強大的技術,利用它可以使位于任何位置的應用程序互相通信,這些應用程序可能在同一臺計算機上運行,也可能位于同一局域網中的不同計算機上,或者位于相隔萬里的有巨大差異的網絡中。
使用.net remoting技術結合ado.net能夠高效、可靠地解決這兩方面的問題。具體表現為,在c#中通過使用.net遠程處理框架能夠方便地解決數據、命令遠程傳遞問題;c#通過ado.net對數據庫進行操作,使分布式數據庫系統中對數據庫的各種操作變得高效、可靠,同時易于解決數據一致性問題。
由于時間關系,程序中仍有部分bug,將在下一步繼續完善,而且,還應進一步完善數據字典,使程序結構更加清晰,增強可擴充性。
收集最實用的網頁特效代碼!
新聞熱點
疑難解答
圖片精選