Need help resolving the error when returning the WCF DataTable service: OutOfMemoryException

I have a WCF service running that is trying to return a DataTable . The service method uses SqlDataReader , and then uses DataTable.Load() to get this data into the DataTable , which it intends to return.

Problem: when the service method returns a large table (I define it in an instant), I get these exceptions in the debug output (they do not damage the service):

The first random error like "System.OutOfMemoryException" occurred in SMDiagnostics.dll

The first case of an exception of type "System.InsufficientMemoryException" occurred in SMDiagnostics.dll

Definition "Large": the returned record set in my testing contains 286760 records, and when this table is exported to text, it is approximately 800 MB. I know that this is all relative, so all this can be meaningless. Basically, I point this out because it seems pretty small to me to rule out memory exceptions, especially in light of the fact that the development machine I'm testing on has 8 GB of memory. Again, all this is relative and possibly inappropriate, but I'm trying to provide enough information.

Here is my connection code:

 NetTcpBinding netBind = new NetTcpBinding(); netBind.Security.Mode = SecurityMode.Transport; netBind.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows; netBind.MaxReceivedMessageSize = Int32.MaxValue; netBind.MaxBufferSize = Int32.MaxValue; netBind.MaxBufferPoolSize = 0; netBind.MaxConnections = 300; netBind.ListenBacklog = 300; netBind.ReaderQuotas = XmlDictionaryReaderQuotas.Max; netBind.PortSharingEnabled = true; netBind.OpenTimeout = new TimeSpan(0, 0, RegistryValues.DatabaseTimeout); netBind.CloseTimeout = new TimeSpan(0, 0, RegistryValues.DatabaseTimeout); netBind.ReceiveTimeout = new TimeSpan(0, 5, 0); netBind.SendTimeout = new TimeSpan(0, 5, 0); netBind.ReliableSession.InactivityTimeout = new TimeSpan(long.MaxValue); netBind.TransferMode = TransferMode.Buffered; uriBuilder = new UriBuilder("net.tcp", connServer, (connPort == -1 ? RegistryValues.ServerPort : connPort), "Data"); epAddress = new EndpointAddress(uriBuilder.Uri); ChannelFactory<IData> iChannel = new ChannelFactory<IData>(netBind, epAddress); iChannel.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Identification; IData svcCon = iChannel.CreateChannel(); ((IClientChannel)svcCon).OperationTimeout = new TimeSpan(long.MaxValue); 

Please note that we are using Buffered transfer mode. I am considering an alternative to Streamed , but this will impose a radical change of structure on the rest of the code ... not what I want to do if there is a solution in the current model. I point out that I just don't think I push excessive amounts of data.

This connection is established as part of creating an object of the Sql class (my class). The iChannel and svcCon are deleted together when the Sql.Dispose() method is Sql.Dispose() because we create these Sql objects with a using block).

Here's the Sql.Dispose() method, which should run my using blocks (in case that matters):

 public void Dispose() { if (this != null && this.connection.State == ConnectionState.Open) ClearConnectionPool(); try { if (iChannel.State != CommunicationState.Faulted) iChannel.Close(); } catch { iChannel.Abort(); } try { if (((IClientChannel)svcCon).State != CommunicationState.Faulted) ((IClientChannel)svcCon).Close(); } catch { ((IClientChannel)svcCon).Abort(); } } 

In conclusion, I create a WCF communication channel, which in turn creates a SqlConnection . Using this, we launch SQL calls. Then all this is removed as quickly as possible. We do not hang these connections longer than necessary to perform the necessary operations with the database. And there are very rare cases when these things are not created in using blocks, which means that I am sure that we are cleaning correctly. Unless, of course, someone sees the problem with my Dispose() method.

Any advice is appreciated. I can provide more code upon request.

Additional information: Here is the stack trace that I get when debugging the client and entering the server code to see what happens when it tries to return a DataTable :

 A first chance exception of type 'System.OutOfMemoryException' occurred in SMDiagnostics.dll A first chance exception of type 'System.InsufficientMemoryException' occurred in SMDiagnostics.dll A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll Step into: Stepping over method without symbols 'System.ServiceModel.Dispatcher.MessageRpc.Process' A first chance exception of type 'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.dll Step into: Stepping over method without symbols 'System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump' A first chance exception of type 'System.IO.IOException' occurred in System.dll Step into: Stepping over method without symbols 'System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest' Step into: Stepping over method without symbols 'System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump' A first chance exception of type 'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.dll Step into: Stepping over method without symbols 'System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame' Step into: Stepping over method without symbols 'System.ServiceModel.AsyncResult.Complete' A first chance exception of type 'System.ServiceModel.CommunicationException' occurred in mscorlib.dll Step into: Stepping over method without symbols 'System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame' Step into: Stepping over method without symbols 'System.ServiceModel.AsyncResult.Complete' A first chance exception of type 'System.ServiceModel.CommunicationObjectFaultedException' occurred in System.ServiceModel.dll Step into: Stepping over method without symbols 'System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame' Step into: Stepping over method without symbols 'System.Net.LazyAsyncResult.Complete' A first chance exception of type 'System.ServiceModel.CommunicationObjectFaultedException' occurred in mscorlib.dll Step into: Stepping over method without symbols 'System.Net.Security.NegotiateStream.ProcessFrameBody' A first chance exception of type 'System.ServiceModel.CommunicationObjectFaultedException' occurred in System.ServiceModel.dll Step into: Stepping over method without symbols 'System.Net.Security.NegotiateStream.ReadCallback' Step into: Stepping over method without symbols 'System.Net.FixedSizeReader.CheckCompletionBeforeNextRead' Step into: Stepping over method without symbols 'System.Net.FixedSizeReader.ReadCallback' Step into: Stepping over method without symbols 'System.ServiceModel.AsyncResult.Complete' Step into: Stepping over method without symbols 'System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame' Step into: Stepping over method without symbols 'System.Threading._IOCompletionCallback.PerformIOCompletionCallback' 
+1
source share
2 answers

Please check the dataContractSerializer attribute in the Behavior section and increase the value to a larger value.

Also check the readerQuotas section, as well as the attributes maxBufferPoolSize, maxBufferSize and maxReceivedMessageSize.

0
source

Change your porting to streaming and web configuration and other configuration ... u can not change web config transfermode if you don't deploy it in your IIS

0
source

Source: https://habr.com/ru/post/1496617/


All Articles