关于WCF客户端与服务端数据事务同步的问题!急……
-
2012年4月18日 5:25
客户端经常掉线,我就想着用WCF事务来做数据同步,现在服务器数据库是ORACLE,客户端数据库是SQLSERVER,我写了一个测试程序,并网数据库里面导入10000条数据,数据同步的时候时不时的拔下网线,结果同步的数据却不一致,废话不多说,直接上代码,请各位大侠指正看哪里不对导致数据不能同步?
客户端执行代码如下:
public override void mySynchronous() { int tableCount = GetTableCount(); string TableCountMessage = string.Format("当前共有未同步数据{0}条!", tableCount); Console.WriteLine(TableCountMessage); if (tableCount > 0) { Console.WriteLine("开始同步数据……"); MyClientService.HelloServiceClient service = new MyClientService.HelloServiceClient(); System.Transactions.TransactionOptions tran = new System.Transactions.TransactionOptions(); //设置事务超时时间 tran.Timeout = new TimeSpan(3000); //设置事务的隔离级别 tran.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead; DataTable myDataTable = GetUserDataTable(); foreach (DataRow dr in myDataTable.Rows) { using (var ts = new System.Transactions.TransactionScope()) { try { string name = dr["testName"].ToString(); string id = dr["userID"].ToString(); if (service.InserOraclData(name, id)) { updateType(id); } else { throw new Exception("服务端插入错误!"); } //service.TransactMyServer(myDataTable); Console.WriteLine(string.Format("{0}数据ID:{1}数据更新成功!", DateTime.Now.ToString(), id)); ts.Complete(); } catch (Exception ex) { Console.WriteLine(DateTime.Now.ToString() + "数据更新失败!失败原因如下:"); Console.WriteLine(ex.Message); Transaction.Current.Rollback(ex); } } } } }服务端InseroraclData方法
/// <summary> /// 添加数据 /// </summary> /// <param name="name"></param> /// <param name="id"></param> [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true )] public bool InserOraclData(string name, string id) { string sql = @"INSERT INTO Test1 (testName ,TYPE ,userID) VALUES (:testName ,'1' ,:userID)"; OracleConnection mycon = myOracleServerData.myConn; OracleCommand mycmd = new OracleCommand(sql,mycon); mycmd.Parameters.Add(new OracleParameter(":testName",name)); mycmd.Parameters.Add(new OracleParameter(":userID",id)); try { mycon.Open(); mycmd.ExecuteNonQuery(); return true; } catch (OracleException ex) { Console.WriteLine(ex); throw ex; } finally { mycon.Close(); } }客户端updateType方法
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true )] public void updateType(string id) { string sql = @"UPDATE Test1 SET [type] = 1 WHERE [userID] = @userID"; SqlConnection myCon = ClientData.myConn; SqlCommand mycmd = new SqlCommand(sql,myCon); mycmd.Parameters.Add(new SqlParameter("@userID",id)); try { myCon.Open(); mycmd.ExecuteNonQuery(); } catch (Exception ex ) { Console.WriteLine(ex.Message); throw ex; } finally { myCon.Close(); } }
- 已编辑 heleicn 2012年4月18日 5:26
全部回复
-
2012年4月18日 7:20各位MVP些……多多指导我们这些菜鸟哦……咋个没有人喂………………………………………………………………………………………………
-
2012年4月18日 7:36版主
2个办法
1.有个问题就是WCF支持事务机制,如果失败可以回滚。这个就是效率低点。
2.还有一个办法就是
你每次插入的时候记录插入的数据的ID,失败的时候Catch异常,把当前插入的ID记录到文件或者别的地方,下一次重新连接,从这个ID记录 插入。这样即使失败 下次重启也不会 重复数据。
后面一个办法操作比较简单,之前我们也用过这个方法
Frank Xu Lei--谦卑若愚,好学若饥
[老徐的网站]:http://www.frankxulei.com/[老徐的博客]:http://54peixun.com/Author/frankxulei
微软WCF中文技术论坛
微软WCF英文技术论坛
Windows Azure中文技术论坛 -
2012年4月18日 7:56
我用了事务的啊……大哥,你看看我代码哪里有问题?
第二个办法是在服务端记录还是在客户端记录啊?
-
2012年4月18日 8:39版主
我用了事务的啊……大哥,你看看我代码哪里有问题?
第二个办法是在服务端记录还是在客户端记录啊?
1.客户端和服务都参与事务,并且要启用MSDTC。这个比较复杂,而且不支持Oracle数据库
2.第二个办法在客户端记录,客户端不是调用插入的方法吗,而且只有客户端知道哪条出错
Frank Xu Lei--谦卑若愚,好学若饥
[老徐的网站]:http://www.frankxulei.com/[老徐的博客]:http://54peixun.com/Author/frankxulei
微软WCF中文技术论坛
微软WCF英文技术论坛
Windows Azure中文技术论坛 -
2012年4月19日 4:45
搞定……TransactionAutoComplete = false
OperationContext.Current.SetTransactionComplete();
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false )] public string InserOraclData(string name, string id) { string sql = @"INSERT INTO Test1 (testName ,TYPE ,userID) VALUES (:testName ,'1' ,:userID)"; OracleConnection mycon = myOracleServerData.myConn; OracleCommand mycmd = new OracleCommand(sql,mycon); mycmd.Parameters.Add(new OracleParameter(":testName",name)); mycmd.Parameters.Add(new OracleParameter(":userID",id)); //string sqlNum = "SELECT COUNT(*) FROM Test1 WHERE userID = :userID "; //OracleCommand mycmd2 = new OracleCommand(sqlNum,mycon); //mycmd2.Parameters.Add(new OracleParameter(":userID",id)); try { mycon.Open(); mycmd.ExecuteNonQuery(); //int k = Convert.ToInt32(mycmd2.ExecuteScalar()); //if (k > 0) //{ OperationContext.Current.SetTransactionComplete(); return id; //} //else //{ // Exception ex =new Exception("数据验证失败!"); // throw ex; //} } catch (OracleException ex) { Console.WriteLine(ex); Transaction.Current.Rollback(ex); throw ex; } catch (InvalidOperationException e) { Transaction.Current.Rollback(e); throw e; } catch (Exception e) { Transaction.Current.Rollback(e); throw e; } finally { try { mycon.Close(); } catch (OracleException ex) { Transaction.Current.Rollback(ex); throw ex; } catch (InvalidOperationException e) { Transaction.Current.Rollback(e); throw e; } catch (Exception ee) { Transaction.Current.Rollback(ee); throw ee; } finally { mycon.Close(); } } }- 已标记为答案 heleicn 2012年4月19日 5:24

