我的WCF服务面临着奇怪的问题。相同的代码工作正常,直到最近我们添加了更多的OperationContracts(Web方法)。
我们有共同的3层架构。
以下是我的快速示例代码:
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>
答案 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 。