远程数据同步(转摘)
远程数据同步
基本结构:
一个中心数据库:db1(包含表t1)
一个终端数据库:db2 (包含表t2)
t1与t2结构完全相同。
现在,我想用一个webservice实现下面的功能:
终端将db2中t2的DataSet传送到webservice,webservice将DataSet中有变化的部分更新到db1的t1中。同理webservice将从db1中t1中得到的DataSet下传到终端,终端将DataSet中的变化部分更新到db2中的t2中。从而达到db1的t1中的数据与db2的t2的数据保持同步。
我想用的是DataAdapter的uodate方法,可是想了半天没搞明白,请各位帮忙看看怎么弄,或还有更好的办法请赐教。
做了个简单模型:
try
{
string str_sconn="data source=(local);initial catalog=cosco_express;password=12345;user id=sa";
string str_oconn=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\db5.mdb";
SqlConnection sconn=new SqlConnection(str_sconn);
OleDbConnection oconn=new OleDbConnection(str_oconn);
SqlDataAdapter sda=new SqlDataAdapter("select * from myuser",sconn);
DataSet sds=new DataSet();
sda.Fill(sds,"myuser");
OleDbDataAdapter oda=new OleDbDataAdapter("select * from myuser",oconn);
OleDbCommandBuilder custCB = new OleDbCommandBuilder(oda);
DataSet ods=new DataSet();
oda.Fill(ods,"myuser");
this.dataGrid1.DataSource=ods.Tables["myuser"].DefaultView;
MessageBox.Show("First!");
//ods.Merge(sds.Tables["myuser"]);
//ods.Merge(sds,false);
//ods.AcceptChanges();
this.dataGrid1.DataSource=ods.Tables["myuser"].DefaultView;
MessageBox.Show("Merged!");
oda.Update(ods,"myuser");//这句没起作用:(
MessageBox.Show("Updated!");
}
catch(System.Exception err)
{
MessageBox.Show(err.Message);
}
中心表里有2条记录,终端表里没有数据,通过datagrid显示数据,开始网格内容为空,后来merge后,网格中显示了两条记录,说明合并成功,但是最后update没起作用,终端表里依然没有数据:(
如果初始时两个数据库中的数据不一样的话,可能你只能自己写一个类来完成类似于Merge的工作:遍历sds的所有记录,与ods比较,如果存在相同主键的记录,就比较他们的各字段,如果不相同,修改ods的记录;如果ods中没有相同主键的记录,就添加新纪录;最后在遍历ods,与sds比较,如果不存在相同主键的记录,则删除ods中相应的记录。
不过这样的方案从各方面考虑都不太佳:(
同意,我也想过这个方法,原来想用的就是dataadapter的update,现在用不成了:(
我的想法是在设计数据库时用几个字段作为标志(insert,update,delete),然后分类取出,再针对每种类别的dataset分别处理。但是如果这样肯定是遍历传过来的datatable的每个datarow,接下来应该怎么做?
我想最笨的办法是把每条datarow用sql语句进行操作(IO操作太多,效率低下),有没有更好的方法呢,如果还能用dataset,全在内存中搞定,批量提交是最好了,可是除了insert操作可能可以以外,delete和update肯定还会有问题:(
我写了一个类,不过限制不少了:),比如要求表一定要有架构。
public class MyMerge
{
public static void Merge(DataSet ds1,string dt1,DataSet ds2,string dt2)
{
object[] newRow=new object[ds1.Tables[dt1].PrimaryKey.Length];
DataColumn[] dc=ds1.Tables[dt1].PrimaryKey;
for (int i=0;i<ds1.Tables[dt1].Rows.Count;i++)
{
for (int k=0;k<newRow.Length;k++)
{
newRow[k]=ds1.Tables[dt1].Rows[i][dc[k].ColumnName];
}
ds2.Tables[dt2].BeginLoadData();
ds2.Tables[dt2].LoadDataRow(newRow,false);
ds2.Tables[dt2].EndLoadData();
}
for (int i=0;i<ds2.Tables[dt2].Rows.Count;i++)
{
for (int k=0;k<newRow.Length;k++)
{
newRow[k]=ds2.Tables[dt2].Rows[i][dc[k].ColumnName];
}
if (!ds1.Tables[dt1].Rows.Contains(newRow))
{
ds2.Tables[dt2].Rows[i].Delete();
}
}
}
}