WCF中运用事务

本文主要内容:1.WCF中运用事务的基本设置;2.代码示例;

一、WCF运用事务的基本设置包括三项:

a.绑定中添加事务流 transactionFlow=true;

b.操作契约中添加[TransactionFlow(TransactionFlowOption....)]属性;

c.服务类中添加事务环境[OperationBehavior(TransactionAutoComlete=true,TransactionScopeRequired=true)];

d.如果服务类的实例不是 InstanceContextMode.PerCall,则需要在[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete=false)];

下面是它们的组合,会产生不同的事务传播模式

绑定事务流

TransactionFlowOption

TransactionScopeRequired

事务模式

False

Allowed

False

None

False

Allowed

True

Service

False

NotAllowed

False

None

False

NotAllowed

True

Service

True

Allowed

False

None

True

Allowed

True

Client/Service

True

Mandatory

False

None

True

Mandatory

True

client

Client/Service模式:客户端包含事务时,以客户端的事务为根;如果客户端没有包含事务,则以服务端为事务的根;

Client模式:始终以客户端的事务为根;

Service模式:以服务端的事务为根;

None模式:没有运用到事务;

二、代码示例:向数据库插入数据

服务端:

操作契约 ITransaction.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.ServiceModel;
 6  namespace TransactionExampleHost
 7  {
 8      [ServiceContract]
 9      public interface ITransaction
10      {
11          [OperationContract]
12          [TransactionFlow(TransactionFlowOption.Allowed)]
13          void ExecuteSql(string sql);
14  
15          [OperationContract]
16          void MethodException();
17      }
18  }

 

服务类 TransactionService.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  
 6  using System.ServiceModel;
 7  namespace TransactionExampleHost
 8  {
 9      [ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete=false,InstanceContextMode=InstanceContextMode.PerCall)]
10      class TransactionService:ITransaction
11      {
12          public TransactionService()
13          {
14              Console.WriteLine("Constructor....");
15          }
16  
17          [OperationBehavior(TransactionAutoComplete=true,TransactionScopeRequired=true)]
18          public void ExecuteSql(string sql)
19          {
20              DbHelper dbHelper = new DbHelper("Data Source=.;Initial Catalog=db_Manager;Integrated Security=True");
21              dbHelper.ExecuteSql(sql);
22          }
23  
24          public void MethodException()
25          {
26              throw new Exception("exception is open");
27          }
28      }
29  }

 

数据库操作类 DbHelper.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.Data;
 6  using System.Data.SqlClient;
 7  namespace TransactionExampleHost
 8  {
 9      class DbHelper
10      {
11          private string conn;
12          public DbHelper(string strCon)
13          {
14              this.conn = strCon;
15          }
16  
17          private SqlConnection Open()
18          {
19              SqlConnection sqlCon = new SqlConnection(conn);
20              if (sqlCon.State != ConnectionState.Open)
21              {
22                  sqlCon.Open();
23              }
24              return sqlCon;
25          }
26  
27          private void Close(SqlConnection sqlCon)
28          {
29              if (sqlCon.State != ConnectionState.Closed)
30              {
31                  sqlCon.Close();
32              }
33          }
34  
35          public void ExecuteSql(string sql)
36          {
37              using (SqlCommand cmd = new SqlCommand())
38              {
39                  cmd.CommandText = sql;
40                  cmd.Connection = this.Open();
41                  cmd.ExecuteNonQuery();
42                  this.Close(cmd.Connection);
43              }
44          }
45      }
46  }

Program.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.ServiceModel;
 6  namespace TransactionExampleHost
 7  {
 8      class Program
 9      {
10          static void Main(string[] args)
11          {
12              ServiceHost host = new ServiceHost(typeof(TransactionService));
13              host.Opened += (r1, r2) => Console.WriteLine("Host is open......\r\nPress any key to exit.....");
14              host.Open();
15              Console.ReadKey();
16          }
17      }
18  }


App.config

 1 <?xml version="1.0" encoding="utf-8" ?>
 2  <configuration>
 3    <system.serviceModel>
 4      <services>
 5        <service name="TransactionExampleHost.TransactionService">
 6          <endpoint address="net.tcp://localhost:6666" binding="netTcpBinding" contract="TransactionExampleHost.ITransaction"
 7                     bindingConfiguration="transactionBinding"></endpoint>
 8        </service>
 9      </services>
10      <bindings>
11        <netTcpBinding>
12          <binding name="transactionBinding" transactionFlow="true">
13            <reliableSession enabled="true"/>
14          </binding>
15        </netTcpBinding>
16      </bindings>
17    </system.serviceModel>
18  </configuration>

 

客户端:

操作契约 ITransaction.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.ServiceModel;
 6  namespace TransactionExampleClient
 7  {
 8      [ServiceContract]
 9      public interface ITransaction
10      {
11          [OperationContract]
12          [TransactionFlow(TransactionFlowOption.Allowed)]
13          void ExecuteSql(string sql);
14  
15          [OperationContract]
16          void MethodException();
17      }
18  }


代理类 TransactionProxy.cs

 

 1 using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.ServiceModel;
 6  using System.ServiceModel.Transactions;
 7  using System.ServiceModel.Channels;
 8  namespace TransactionExampleClient
 9  {
10      class TransactionProxy:ClientBase<ITransaction>,ITransaction
11      {
12          public TransactionProxy()
13              : base()
14          { }
15  
16          public TransactionProxy(string configurationName):base(configurationName)
17          {}
18  
19          public void ExecuteSql(string sql)
20          {
21              base.Channel.ExecuteSql(sql);
22          }
23  
24          public void MethodException()
25          {
26              base.Channel.MethodException();
27          }
28      }
29  }

创建窗体,并且添加一按钮,执行以下事件:

 

 1 private void btnExecuteProxy_Click(object sender, EventArgs e)
 2          {
 3              try
 4              {
 5                  using (TransactionScope scope = new TransactionScope())
 6                  {
 7                      TransactionProxy proxy = new TransactionProxy("dbTransaction");
 8                      string sql = "insert into userinfo(UserId,name,age) values(24,'aa',1)";
 9                      proxy.ExecuteSql(sql);
10  
11                      TransactionProxy proxy2 = new TransactionProxy("dbTransaction");
12                      string sql2 = "insert into userinfo(UserId,name,age) values(25,'aa',1)"//如果需要测试回滚,可以将SQL语句写错
13                      proxy2.ExecuteSql(sql2);
14  
15                      scope.Complete();  //此处提交事务。如果没有执行此方法,事务就会回滚。
16                      MessageBox.Show("Execute finish!");
17  
18                  }
19              }
20              catch (Exception ex)
21              {
22                  MessageBox.Show("Test", ex.Message);
23              }
24          }

 

app.config:

 

 1 <?xml version="1.0" encoding="utf-8" ?>
 2  <configuration>
 3    <system.serviceModel>
 4      <client>                                                                                                                      
 5        <endpoint name="dbTransaction" address="net.tcp://localhost:6666" binding="netTcpBinding" contract="TransactionExampleClient.ITransaction"
 6                   bindingConfiguration="transactionBinding"></endpoint>
 7      </client>
 8      <bindings>
 9        <netTcpBinding>
10          <binding name="transactionBinding" transactionFlow="true" >
11            <reliableSession  enabled="true"/>
12            <security></security>
13          </binding>
14        </netTcpBinding>
15      </bindings>
16    </system.serviceModel>
17  </configuration>

 

另外需要在数据库创建一测试表userinfo:包含(UserId,name,age)这三字段。

参考文献:《WCF 服务编程》

转载自:http://www.cnblogs.com/xyz168/archive/2011/09/29/2195144.html

posted @ 2012-03-01 13:31  root7  阅读(281)  评论(0)    收藏  举报