服务操作需要流动事务

时间:2009-11-09 17:56:53

标签: wcf

我的WCF服务面临着奇怪的问题。相同的代码工作正常,直到最近我们添加了更多的OperationContracts(Web方法)。

我们有共同的3层架构。

  • DAL(WCF)
  • BLL
  • 网络用户界面

以下是我的快速示例代码:

DAL(WCF):

[ServiceContract]
interface IPerson
{
   [OperationContract]
   [TransactionFlow(TransactionFlowOption.Mandatory)]
   int AddPerson(Person p);
}


// AddPerson is implemented in the service
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int AddPerson(Person p)
{
  // LINQ DataContext stuff goes here
}

BLL:

public class EmployeeBLL 
{
   public void AddNewEmployee(Person p)
   {
       using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
            {
                try
                {
                   PersonClient perClient = new PersonClient();
                   int personId = perClient.AddPerson(p);
                   ts.Complete();
                }
                catch (Exception ex)
                {
                   // Log exception
                }
                finally
                {
                    ts.Dispose();
                }
            }
            perClient.Close();
   }
}

Web UI中的用法:

EmployeeBLL empBLL = new EmployeeBLL ()
empBLL.AddNewEmployee(person);

我得到“服务操作需要流动的事务。”尝试在服务中调用AddPerson方法时在我的BLL中。在web.config中启用跟踪后运气不太好。

详细的堆栈跟踪:

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

客户端配置:

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IEmployee" closeTimeout="00:01:00"
              openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
              bypassProxyOnLocal="false" transactionFlow="true" hostNameComparisonMode="StrongWildcard"
              maxBufferPoolSize="524288" maxReceivedMessageSize="5000000"
              messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
              allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
          <security mode="Message">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true"
            algorithmSuite="Default" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:2882/Test.svc"
          binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IEmployee"
          contract="Test.IEmployee" name="WSHttpBinding_IEmployee">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
</system.serviceModel>

4 个答案:

答案 0 :(得分:2)

我终于明白了!我使用svcutil工具手动生成服务引用代理类和配置文件,并在BLL中使用。工作得很好!

VS版本:2008

WCF服务在BLL中被引用为“服务引用”。更新WCF“服务引用”后,Reference.cs(代理类)中最近添加的ServiceContract的OperationContracts缺少TransactionFlow属性。这主要是在向服务添加新的ServiceContracts之后开始的。一个有趣的事情是,app.config为新添加的ServiceContract <CustomBinding>代替了<wsHttpBinding>.似乎是VS 2008生成服务参考的方式。

答案 1 :(得分:1)

问题不在于您的服务,而是在您的客户端代码中。您定义的服务操作要求您使用已在客户端启动的事务来调用它。客户端的呼叫是在TransactionScope吗?

答案 2 :(得分:0)

您是否尝试过添加

[OperationBehavior(TransactionScopeRequired=true)] 

合同的实施

修改 只是为了踢,您尝试重新生成客户端代理吗?

答案 3 :(得分:0)

您必须手动在客户端配置上添加transactionFlow选项,因为通过添加服务引用添加服务代理将不包括transactionFlow属性。
这是设计的。即使你在服务中添加trasactionFlow = true,当你通过添加服务引用来添加它时,它在客户端配置中也是假的。

您需要做什么才能找到 transactionFlow 属性并将其设置为 true

交易流程的三个必要步骤
1.使用属性 [Transaction(TransactionFlowOption.Allowed)]
标记服务合同 2.为代码添加transactino支持,即操作将OperationBehaviour属性的set属性设置为 [OperationBehaviour(TransactionScopeRequired = true)]
3.在服务器和客户端上添加bindingConfiguration和 TransactionFlow = true