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

View Code
 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

View Code
 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

View Code
 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

View Code
 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

View Code
 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

View Code
 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

View Code
 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 }

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

View Code
 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:

View Code
 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 服务编程》




posted @ 2011-09-29 10:02  走过留痕  阅读(3159)  评论(3编辑  收藏  举报