Posted on 2009-05-30 23:41
Frank Xu Lei 阅读(375)
评论(2)
编辑
收藏
网摘 所属分类:
WCF分布式开发常见错误
WCF事务编程过程中,会出现这个操作无效异常。信息如下:
At least one operation on the 'WCFServiceTransaction1' contract is configured with the TransactionFlowAttribute attribute set to Mandatory but the channel's binding 'NetTcpBinding' is not configured with a TransactionFlowBindingElement. The TransactionFlowAttribute attribute set to Mandatory cannot be used without a TransactionFlowBindingElement.
异常界面如图:
![](https://i-blog.csdnimg.cn/blog_migrate/5bfcd012b50b8c2a891cf9cb0ef9482f.gif)
我是在调试客户端事务模式的时候出现的错误,服务契约和服务类的代码如下:
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Transactions;
using System.Diagnostics;
// ServiceContract 属性以及 Indigo 使用的所有其他属性均在 System.ServiceModel 命名空间中定义,
// 因此本例开头使用 using 语句来引用该命名空间。
namespace WCFService
{
// 1.服务契约
[ServiceContract(Namespace = " http://www.cnblogs.com/frank_xl/ " )]
public interface IWCFServiceTransaction1
{
// 操作契约
[OperationContract]
// 强制事务流,使用客户端事务
// [TransactionFlow(TransactionFlowAttribute
[TransactionFlow(TransactionFlowOption.Mandatory)]
bool AddNewData( string name);
}
// 2.服务类,实现契约
// 事务有10分钟的超时限制
// [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[ServiceBehavior(IncludeExceptionDetailInFaults = true , TransactionTimeout = " 00:30:00 " )]
public class WCFServiceTransaction1 : IWCFServiceTransaction1
{
// 实现接口定义的方法
// 需要事务环境,启动事务
[OperationBehavior(TransactionScopeRequired = true , TransactionAutoComplete = true )]
public bool AddNewData( string name)
{
Transaction transaction = Transaction.Current;
Debug.Assert(System.Transactions.Transaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty);
Console.WriteLine( " Create a new Transaction at {0} " , System.Transactions.Transaction.Current.TransactionInformation.CreationTime);
Console.WriteLine( " WCFService 1 Transaction Status is {0} " , System.Transactions.Transaction.Current.TransactionInformation.Status);
Console.WriteLine( " WCFService 1 Transaction LocalIdentifier is {0} " , System.Transactions.Transaction.Current.TransactionInformation.LocalIdentifier);
Console.WriteLine( " WCFService 1 Transaction DistributedIdentifier is {0} " , System.Transactions.Transaction.Current.TransactionInformation.DistributedIdentifier);
// using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
// {
try
{
using (userTableAdapter adapter = new userTableAdapter())
{
if ( 1 == adapter.CreateUser(name))
{
Console.WriteLine( " Calling WCF Transaction sucessfully
name length is:{0}
"
, name.Length);
}
else
{
Console.WriteLine( " Calling WCF Transaction unsucessfully
name length is:{0}
"
, name.Length);
// return false;
}
}
}
catch (Exception e)
{
Console.WriteLine( " Calling WCF Transaction error:{0} " , e.Message);
throw e;
// return false;
}
// ts.Complete();
return true ;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Transactions;
using System.Diagnostics;
// ServiceContract 属性以及 Indigo 使用的所有其他属性均在 System.ServiceModel 命名空间中定义,
// 因此本例开头使用 using 语句来引用该命名空间。
namespace WCFService
{
// 1.服务契约
[ServiceContract(Namespace = " http://www.cnblogs.com/frank_xl/ " )]
public interface IWCFServiceTransaction1
{
// 操作契约
[OperationContract]
// 强制事务流,使用客户端事务
// [TransactionFlow(TransactionFlowAttribute
[TransactionFlow(TransactionFlowOption.Mandatory)]
bool AddNewData( string name);
}
// 2.服务类,实现契约
// 事务有10分钟的超时限制
// [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[ServiceBehavior(IncludeExceptionDetailInFaults = true , TransactionTimeout = " 00:30:00 " )]
public class WCFServiceTransaction1 : IWCFServiceTransaction1
{
// 实现接口定义的方法
// 需要事务环境,启动事务
[OperationBehavior(TransactionScopeRequired = true , TransactionAutoComplete = true )]
public bool AddNewData( string name)
{
Transaction transaction = Transaction.Current;
Debug.Assert(System.Transactions.Transaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty);
Console.WriteLine( " Create a new Transaction at {0} " , System.Transactions.Transaction.Current.TransactionInformation.CreationTime);
Console.WriteLine( " WCFService 1 Transaction Status is {0} " , System.Transactions.Transaction.Current.TransactionInformation.Status);
Console.WriteLine( " WCFService 1 Transaction LocalIdentifier is {0} " , System.Transactions.Transaction.Current.TransactionInformation.LocalIdentifier);
Console.WriteLine( " WCFService 1 Transaction DistributedIdentifier is {0} " , System.Transactions.Transaction.Current.TransactionInformation.DistributedIdentifier);
// using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
// {
try
{
using (userTableAdapter adapter = new userTableAdapter())
{
if ( 1 == adapter.CreateUser(name))
{
Console.WriteLine( " Calling WCF Transaction sucessfully
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
}
else
{
Console.WriteLine( " Calling WCF Transaction unsucessfully
![](https://i-blog.csdnimg.cn/blog_migrate/b854634c0904529d4018c4c3336be836.gif)
// return false;
}
}
}
catch (Exception e)
{
Console.WriteLine( " Calling WCF Transaction error:{0} " , e.Message);
throw e;
// return false;
}
// ts.Complete();
return true ;
}
}
}
我查阅到的资料:
1.http://social.msdn.microsoft.com/Forums/en-US/windowstransactionsprogramming/thread/d3020922-92b3-4dc5-ab22-b8fe34cbf40e;这个是属性没定义在操作契约上。
2.http://blogs.msdn.com/thelever/archive/2007/03/29/configuration-of-transactions-of-use-in-wcf.aspx;这个建议更换[TransactionFlow(TransactionFlowOption.Allowed)].
可以解决问题。但是我不能这样。
我这里是为了测试客户端事务模式写的代码。
所以大家都什么好的解决办法~谢谢
1.http://social.msdn.microsoft.com/Forums/en-US/windowstransactionsprogramming/thread/d3020922-92b3-4dc5-ab22-b8fe34cbf40e;这个是属性没定义在操作契约上。
2.http://blogs.msdn.com/thelever/archive/2007/03/29/configuration-of-transactions-of-use-in-wcf.aspx;这个建议更换[TransactionFlow(TransactionFlowOption.Allowed)].
可以解决问题。但是我不能这样。
我这里是为了测试客户端事务模式写的代码。
所以大家都什么好的解决办法~谢谢
3.已经找到解决办法:
使用配置文件方式:
添加一个绑定协议节点,。也可以使用编程方式。这里给出代码:
<
bindings
>
< netTcpBinding >
< binding name = " netTcpBindingTcp " transactionFlow = " true " transactionProtocol = " WSAtomicTransactionOctober2004 " >
<!--< reliableSession enabled = " true " ordered = " true " />
< security mode = " None " ></ security >-->
</ binding >
</ netTcpBinding >
</ bindings >
< netTcpBinding >
< binding name = " netTcpBindingTcp " transactionFlow = " true " transactionProtocol = " WSAtomicTransactionOctober2004 " >
<!--< reliableSession enabled = " true " ordered = " true " />
< security mode = " None " ></ security >-->
</ binding >
</ netTcpBinding >
</ bindings >
然后在服务终结点里使用这个配置:
<
endpoint
address = " net.tcp://localhost:9002/WCFServiceTransaction2 "
bindingConfiguration = " netTcpBindingTcp "
binding = " netTcpBinding "
contract = " WCFService.IWCFServiceTransaction2 " >
</ endpoint >
address = " net.tcp://localhost:9002/WCFServiceTransaction2 "
bindingConfiguration = " netTcpBindingTcp "
binding = " netTcpBinding "
contract = " WCFService.IWCFServiceTransaction2 " >
</ endpoint >
【老徐的博客】
【作者】:Frank Xu Lei
【地址】:http://www.cnblogs.com/frank_xl/archive/2009/05/30/1492513.html