开发环境:使用的WCF4.0+ SL
事务控制:使用WCF自带事务参数控制
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)].
由于程序处理时,时间大概>=10分钟,报错。
把那些 Timeout 都设置大于 10 分钟。
早上好!
我是这样设置的,您看下.
SL :
1 <configuration> 2 <system.serviceModel> 3 <bindings> 4 <basicHttpBinding> 5 <binding name="BasicHttpBinding_WcfService" closeTimeout="00:01:00" 6 openTimeout="00:01:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" 7 maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> 8 <security mode="None" /> 9 </binding> 10 </basicHttpBinding> 11 </bindings> 12 <client> 13 <endpoint address="http://localhost/XXXX/WCFService/WcfService.svc" 14 binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_WcfService" 15 contract="WcfServiceClient.WcfService" name="BasicHttpBinding_WcfService" /> 16 </client> 17 </system.serviceModel> 18 </configuration>
服务器端:
1 <behaviors> 2 <serviceBehaviors> 3 <behavior name=""> 4 <serviceMetadata httpGetEnabled="true" /> 5 <serviceDebug includeExceptionDetailInFaults="false" /> 6 <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 7 <serviceTimeouts transactionTimeout="01:00:00" /> 8 </behavior> 9 </serviceBehaviors> 10 </behaviors> 11 <bindings> 12 <basicHttpBinding> 13 <binding name="LargeDataTransferServicesBinding" 14 maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> 15 </binding> 16 <binding name="BasicHttpBinding_WcfService" closeTimeout="00:01:00" 17 openTimeout="00:01:00" receiveTimeout="01:00:00" sendTimeout="01:00:00" 18 maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> 19 <readerQuotas maxStringContentLength="2147483647"/> 20 <security mode="None" /> 21 </binding> 22 </basicHttpBinding> 23 </bindings>
外加服务端的这个设置:
1 <system.transactions> 2 <defaultSettings timeout="01:00:00"/> 3 </system.transactions>
@宝宝,爸爸爱你: 你是如何使用 SQL 事务的?
@Launcher: 我没有使用SQL事务,使用的是WCF的事务控制。
SQL执行如下:
1 DataTable dtRt = null; 2 3 try 4 { 5 SqlCommand cmd = new SqlCommand(strSql, sqlConn); 6 cmd.CommandType = CommandType.Text; 7 cmd.CommandTimeout = 1800; 8 SqlDataAdapter da = new SqlDataAdapter(cmd); 9 dtRt = new DataTable(); 10 da.Fill(dtRt); 11 return dtRt; 12 } 13 catch (Exception ex) 14 { 15 throw ex; 16 }
@宝宝,爸爸爱你: 你的 sqlConn 在哪儿实例化的?
@Launcher: 在构造函数中实例化的
Code :
1 private SqlConnection sqlConn = null; 2 3 /// <summary> 4 /// 构造函数 5 /// </summary> 6 /// <param name="baseInfo">日志信息</param> 7 public SqlHelper(BaseInfo baseInfo) 8 { 9 //连接字符串 10 string conString = ConfigurationManager.AppSettings["SQLServerDBConnStr"].ToString(); 11 sqlConn = new SqlConnection(conString); 12 logCon = new SqlConnection(conString); 13 this.baseInfo = baseInfo; 14 }
@宝宝,爸爸爱你: 改成函数的局部变量,使用完即释放。
@Launcher:
关键是,我的业务处理还没有完成,这时,SqlConnection还不能释放,但是WCF事务已经完成了。
@宝宝,爸爸爱你:你能给我举一个列子说明“业务处理还没有完成,SqlConnection还不能释放”吗?
@Launcher:
现在我conn.Open(),
由于使用WCF控制,我还不确定,什么时候开启的事务。
在处理业务数据,对数据进行业务检查,需要执行SQL文
WCF事务自动完成
conn.CLose()
以上为正常流程。
异常流程就出现了:由于业务数据检查耗时长,导致了WCF事务关闭先执行了。
@Launcher:
以上说法有点错误哈,
按照提示的错误信息来看:
与当前连接相关联的事务已经完成,但尚未释放。必须先释放该事务,然后才能使用该连接来执行 SQL 语句
应该是我连接先关闭了,但是WCF事务没有释放,但是在查看连状态是 Open 的。
@宝宝,爸爸爱你: 你这表达能力太差了,你还是把你的那个标记了事务的 wcf 服务类源码给贴出来吧。
@Launcher:
WCF :
1 [OperationContract] 2 [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 3 public int IPO0101_SaveInfos( 4 BaseInfo baseInfo, 5 ObservableCollection<IPO0101DTO> oceInputEntity, 6 ObservableCollection<string> ocsRelatedEngine, 7 out string logFilePath) 8 { 9 IPO0101Business myBussiness = new IPO0101Business(); 10 return myBussiness.SaveInfos( 11 baseInfo, 12 oceInputEntity, 13 ocsRelatedEngine, 14 out logFilePath); 15 }
业务处理:
1 public int SaveInfos( 2 BaseInfo baseInfo, 3 ObservableCollection<IPO0101DTO> oceInputEntity, 4 ObservableCollection<string> ocsRelatedEngine, 5 out string logFilePath) 6 { 7 //创建连接数据库方法 8 SqlHelper con = new SqlHelper(baseInfo); 9 List<SqlParameter> sqlParmlist = new List<SqlParameter>(); 10 SqlParameter para = new SqlParameter(); 11 string sql; 12 string SQL = ""; 13 DataTable existDT = new DataTable(); 14 DataTable DTComper = new DataTable(); 15 con.Open(); 16 int intMaxID = 0; 17 //int virtualID = 1; 18 19 //...................................................... 20 // 此处为业务处理,多次调用了SQL执行 21 // 在执行的过程中,给出了错误提示 22 // ...................................................... 23 24 con.Close(); 25 return rtCode;
@宝宝,爸爸爱你: 假设有 5 次调用 SQL 执行,提示错误总是在第几次给出,还是经过多长时间间隔就会给出?
@Launcher:
的确总会在一个位置上提示错误,时间是10分钟~13分钟
@宝宝,爸爸爱你: Timeout 的问题,<behavior name=""> 给个名字,然后给服务指定上
@Launcher:
指定服务,您说的是哪个服务,
现已指定的TimeOut :
<serviceTimeouts transactionTimeout="01:00:00" />
<defaultSettings timeout="01:00:00"/>
@宝宝,爸爸爱你:
<services>
<service behaviorConfiguration="NewBehavior" name="Learn.Library.WCF.MyService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MyService" />
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding"
contract="Learn.Library.WCF.IContract" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
@Launcher:
按照您的代码调整我的配置文件,
报错:在服务 WcfService 实现的协定列表中找不到协定名称 "IMetadataExchange"。将 ServiceMetadataBehavior 添加到配置文件或直接添加到 ServiceHost,以启用对该协定的支持。
@Launcher:
1 <behaviors> 2 <serviceBehaviors> 3 <behavior name="WebApp.WCFService.WcfService"> 4 <serviceMetadata httpGetEnabled="true" /> 5 <serviceDebug includeExceptionDetailInFaults="false" /> 6 <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 7 <serviceTimeouts transactionTimeout="01:00:00" /> 8 </behavior> 9 </serviceBehaviors> 10 </behaviors> 11 <bindings> 12 <basicHttpBinding> 13 <binding name="LargeDataTransferServicesBinding" 14 maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> 15 </binding> 16 <binding name="BasicHttpBinding_WcfService" closeTimeout="00:01:00" 17 openTimeout="00:01:00" receiveTimeout="0:01:00" sendTimeout="01:00:00" 18 maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> 19 <readerQuotas maxStringContentLength="2147483647"/> 20 <security mode="None" /> 21 </binding> 22 </basicHttpBinding> 23 </bindings> 24 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" 25 multipleSiteBindingsEnabled="true" /> 26 <services> 27 <service name="WebApp.WCFService.WcfService"> 28 <host> 29 <baseAddresses> 30 <add baseAddress="http://localhost/XXXX/WCFService/WcfService.svc"/> 31 </baseAddresses> 32 </host> 33 <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_WcfService" 34 contract="WebApp.WCFService.WcfService" /> 35 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 36 </service> 37 </services>
加上了服务名称。
@宝宝,爸爸爱你: <host>.....</host> 就不要了,<endpoint address="mex"...../> 也删除掉
@Launcher:
大神这样,还是不行,依然报错。
@宝宝,爸爸爱你: 你给 wcf 服务配置个日志,然后把日志贴出来。
@Launcher: 是不是这个?
@宝宝,爸爸爱你: 网上翻翻,有没有别的错误。
@Launcher:
上面的都是几天前执行的,同一个错误提示。
@宝宝,爸爸爱你:
[ServiceBehavior(TransactionTimeout = "01:00:00")]
class P001001_Saveinfos
@Launcher:
有这样一个问题,我没有描述:
就是在foreach 循环中,循环次数 6000+
循环过程中,执行了20+的数据库操作
循环完成就需要执行 6000 * 20 的数据库操作。
我判断不出这个的影响,就没有说。
@宝宝,爸爸爱你: 你提的这个现象只是涉及到事务的容量问题,不太确定有关,你可以放到下面的代码中测试下:
using (System.Transactions.TransactionScope myTransaction = new
System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew, newTimeSpan(0, 0, 0, 10, 250)))
{
}
@Launcher:
这个是否需要更新WCF ?
没有更新WCF ,还是报错,WCF日志还是一样。
@Launcher:
嗯,好的,我先用声明的事务测试下。
@宝宝,爸爸爱你:
在配置文件中添加这个:
<system.transactions>
<machineSettings maxTimeout="01:00:00"/>
<defaultSettings timeout="01:00:00"/>
</system.transactions>
@Launcher:
不好意思,回复晚了。
这个配置,我测试下。
测试后,给答案。
现在调整了事务处理,使用SQL事务,不使用WCF事务了。
谢谢您的解答。
@Launcher:
测试测试,还是不行。
@宝宝,爸爸爱你: <machineSettings maxTimeout="01:00:00"/> 这个添加在 Machine.Config 中,x86 和 x64 的都要添加。从 .Net 4 开始 TransactionScope 的 Timeout就不允许代码指定了,所以这样的语句(TransactionScope(TransactionScopeOption.RequiresNew, newTimeSpan(1,0,0)))不会起作用,Timeout 还是按照最大 10 分钟来设定。
@Launcher:
您好!
您说的machine.config 配置IIS吗?
@Launcher:
谢谢。