关于WCF客户端与服务端数据事务同步的问题!急……

已答复 关于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
    •