一、服务器A和服务器B为对方设置专门的数据库查询接口,通过SOAP或者HTTP协议形成相互通讯的功能。
数据编辑操作实现服务器相互通信的功能示例(服务器A和服务器B):服务器A为服务器提B供web service专用服务接口,在用户进行数据编辑(服务器A端的消息)操作动作消息的时候,服务器A先通过接口查询服务器B上的所字条所处的状态(空闲或编辑状态),同时查询本服务器上的编辑字条的所处的状态。如果有一方处于编辑状态,禁止本客户端多字条的编辑,如果双方查询到的状态都是处于闲状态,则改变本服务器上的数据中的字条状态为编辑状态进行锁定,然后进入编辑,编辑完成后,对编辑字条的状态进行初始化,防止多个客户端对数据库中的同条字段进行编辑操作,造成数据的不同步和紊乱。
服务器A和服务器B进行通信实现方式如图1所示:
二、此方案需要保证基础条件:
(1) 服务器的高性能处理能力。
(2) 网络宽带的高稳定性和异常情况的低概率。
(3) 用户操作的及时性和保证不跨浏览器的情况下一次性的数据编辑的完成。
本方案设计的具体实现技术路线
以上的实现功能,可以通过流程图提现如图所示:
三、具体实现过程(实验)
1 数据库的设计
新建数据库A(ceshi1) id的增长值初始值1,增长值2累加,用程序控制
create table customers(id int not null, name varchar(15),editstate int default 0,editpersonalid int default 0,state int default 0,useable int default 0);
1、editstate为0此字段为空闲状态,1为在编辑忙碌状态
2、editpersonalid为0此字段没有编辑人员在编辑状态,此外记录编辑人员的唯一标识
3、state为0此字段为空闲状态,1为批量在编辑状态
4、useable为0此字段可查询,1此字段为删除不可用状态
新建数据库B(ceshi2) id的增长值初始值1,增长值2累加,用程序控制
create table customers(id int not null, name varchar(15),editstate int default 0,editpersonalid int default 0,state int default 0,useable int default 0);
1、editstate为0此字段为空闲状态,1为在编辑忙碌状态
2、editpersonalid为0此字段没有编辑人员在编辑状态,此外记录编辑人员的唯一标识
3、state为0此字段为空闲状态,1为批量在编辑状态
4、useable为0此字段可查询,1此字段为删除不可用状态
2 数据库web service接口设计(实现数据双向同步:以数据插入数据同步实现为例)
2.1 数据库的查询方案设计
数据库的查询,用户A和用户B分别独立查询数据库A和数据库 B,独立进行操作。
2.2 实现数据字条状态查询、状态改变及字条信息查询的接口设计
数据库A单字条编辑状态接口设计:
[WebMethod(Description="根据需要编辑的字条ID查询该字条的先在所处的状态")]
public int DetTheMessageState(int MessageID) {
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
try
{
SqlDataAdapter sda = new SqlDataAdapter("select * from customers where id=" + MessageID, conn);
DataTable dt = new DataTable();
sda.Fill(dt);
string state = dt.Rows[0][1].ToString();
if (state == null || state == "")
{ return 2; //数据库中无此字条具体的信息
}
return 1;
}
catch (Exception ex)
{
Console.Write(ex.Message);
return 0;
}
}
数据库A判断单字条编辑状态接口设计:
[WebMethod(Description = "根据提供的字条key判断是否已存在")]
public int judgeExist(string key) {
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
try
{
SqlDataAdapter sda = new SqlDataAdapter("select * from customers where name='" + key +"'", conn);
DataTable dt = new DataTable();
sda.Fill(dt);
string id=dt.Rows[0][0].ToString();
if (id == null || id == "")
{ return 0; }
else
return 1;
}
catch(Exception ex) {
Console.WriteLine(ex.Message);
return 0;
}
}
数据库A单字条编辑状态更改接口设计:
[WebMethod(Description = "根据需要编辑的字条ID查询该字条的状态并根据需要修改先在所处的状态")]
public int AlertTheMessageState(int MessageID)
{
//数据库的查连接
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
//数据库的查询 try
{
SqlDataAdapter sda = new SqlDataAdapter("select * from customers where id=" + MessageID, conn);
DataTable dt = new DataTable();
sda.Fill(dt);
int state = (int)dt.Rows[0][2];
string name = dt.Rows[0][1].ToString();
conn.Close();
if (name != null && name != "")
{
if (state == 0)
{
SqlConnection conn1 =new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn1.Open();
string strCmd = "UPDATE customers SET state = 1 WHERE id=" + MessageID;
try
{
SqlCommand sqlComm =new SqlCommand();
sqlComm.Connection = conn1;
sqlComm.CommandText = strCmd;
sqlComm.ExecuteNonQuery();
conn1.Close();
return 1;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return 0;
}
}
else
return 2;
}
else
return 3;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return 0;
}
}
数据库A单字条插入和数据库B同步实现接口设计:
[WebMethod(Description = "根据提供的数据字条进行数据的插入")]
public int insertDB(int MessageID,string Name) {
//数据库的查连接
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "INSERT INTO customers (id,name) VALUES(" + MessageID +",'" + Name + "')";
cmd.ExecuteNonQuery();
conn.Close();
return 1;
}
catch(Exception ex) {
Console.Write(ex.Message);
return 0;
}
return 0;
}
数据库A单字条查阅匹配:
[WebMethod(Description = "根据字条的字段,判断该字条是否存在")]
public int sendMessageArray(int MessageID,string Name) {
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
try
{
SqlDataAdapter sda = new SqlDataAdapter("select * from customers where id=" + MessageID+" and name='"+Name+"'", conn);
DataTable dt = new DataTable();
sda.Fill(dt);
string id = dt.Rows[0][0].ToString();
if (id == null || id == "")
{ return 0; }
return 1;
}
catch (Exception ex)
{
Console.Write(ex.Message);
return 0;
}
}
数据库A单字条依照数据库B单字条修改:
[WebMethod(Description = "根据字条的字段进行修改本字条")]
public int updateMessageArray(int MessageID,string Name)
{
SqlConnection conn = new SqlConnection("server=.;database=ceshi1;integrated security=True");
conn.Open();
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "UPDATE customers SET name='"+Name+"' WHERE id="+MessageID;
cmd.ExecuteNonQuery();
conn.Close();
return 1;
}
catch (Exception ex)
{
Console.Write(ex.Message);
return 0;
}
}
Vs调用示例:
protected void sendName_Click(object sender,EventArgs e) {
SqlConnection myconn = new SqlConnection("server=.;database=ceshi2;integrated security=True");
myconn.Open();
int personalID=0;
try {
SqlCommand da = new SqlCommand("select max(id) as maxid from customers where id%2=0", myconn);
SqlDataReader ds = da.ExecuteReader();
ds.Read();
if(ds["maxid"]!=null)
{
personalID =Convert.ToInt32(ds["maxid"]);
}
else{
personalID = 0;
}
// if (persoanID> 0)
personalID = personalID + 2;
// Response.Write("<script>alert(" + Convert.ToInt32(personalID) + ");</script>");测试
}
catch(Exception ex)
{
personalID = personalID + 2;
Console.WriteLine(ex.Message);
// Response.Write("<script>alert(" + Convert.ToInt32(personalID) + ");</script>");测试
}
myconn.Close();
myconn.Open();
int comeback = 0;
string Name=aname.Value.ToString();
if (Name != null&&Name!="")
{ //查询本数据库本信息是否在本地数据库存在
int namenum = 0;
try
{
SqlDataAdapter sda =new SqlDataAdapter("select * from customers where name='" + Name +"'", myconn);
DataTable dt = new DataTable();
sda.Fill(dt);
string id=dt.Rows[0][0].ToString();
if (id != null && id != "")
{
namenum = 1;
}
else
namenum = 0;
}
catch(Exception ex){
Console.WriteLine(ex.Message);
namenum = 0;
}
localhost.Service service =new localhost.Service();
//查询远程服务器数据库 查询此字条是否已经存在
int comeExist = service.judgeExist(Name);
if(comeExist==0&&namenum==0)
{
comeback = service.insertDB(Convert.ToInt32(personalID),Name.ToString());
string str = "INSERT INTO customers (id,name) VALUES(" + personalID + ",'" + Name + "')";
SqlCommand cmd =new SqlCommand(str, myconn);
cmd.ExecuteNonQuery();
myconn.Close();
if (comeback == 1)
{
Response.Write("<script>alert('插入数据库的双向同步成功!!!'); history.go(-1);</script>");
}
else
{
Response.Write("<script>alert('插入数据库的双向同步失败!!!'); history.go(-1);</script>");
}
}
if (comeExist == 1 && namenum == 0)
{
Response.Write("<script>alert('远程数据库中数据已经存在!!!'); history.go(-1);</script>");
}
if (comeExist == 0 && namenum == 1)
{
Response.Write("<script>alert('本地数据库中数据已经存在!!!'); history.go(-1);</script>");
}
if (comeExist == 1 && namenum == 1)
{
Response.Write("<script>alert('数据库中数据已经存在!!!'); history.go(-1);</script>");
}
else
{
Response.Write("<script>alert('处理异常!!!'); history.go(-1);</script>");
}
}
else {
Response.Write("<script>alert('姓名不能为空!!!'); history.go(-1);</script>");
}
}
2.3 数据同步的手动API设计(RESET API设计)
手动实现数据的同步是对数据库A和数据库B实现特定时间的一次性更新,对数据编辑出现的异常情况进行统一处理,使服务器不必为异常的情况出现时,做一些踏步等待或者停止去处理一下异常,留给服务器更多的时间对数据的编辑进行处理。