を返そうとする WCF サービスを実行していDataTable
ます。サービス メソッドは を使用しSqlDataReader
、 を使用して、返す予定DataTable.Load()
の にそのデータを取得します。DataTable
問題: サービス メソッドが大きなテーブルを返す場合 (これについてはすぐに定義します)、デバッグ出力に次の例外が表示されます (サービスが機能しなくなるわけではありません)。
タイプ 'System.OutOfMemoryException' の初回例外が SMDiagnostics.dll で発生しました
タイプ 'System.InsufficientMemoryException' の初回例外が SMDiagnostics.dll で発生しました
「大」の定義: テストで返されたレコード セットには 286760 レコードが含まれており、このテーブルをテキストにエクスポートすると、サイズは約 800MB になります。私はこれがすべて相対的であることを知っているので、それはすべて無意味かもしれません. ほとんどの場合、これを指摘するのは、特に私がテストしている開発マシンに 8GB のメモリがあるという事実に照らして、メモリ例外をスローするのはかなり小さいと思われるからです。繰り返しますが、それはすべて相対的なものであり、おそらく無関係ですが、十分な情報を提供しようとしています.
これが私の接続コードです:
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);
Buffered
転送モードを使用していることに注意してください。別の方法を検討していStreamed
ますが、それはコードの残りの部分に根本的な構造の変更を課すことになります...現在のモデル内に解決策がある場合、私がやりたいことではありません。私は、私が法外な量のデータをプッシュしているとは思わないという事実を指摘しておきます。
この接続は、Sql
クラス オブジェクト (my クラス) の作成の一部として確立されます。およびオブジェクトは、メソッドが呼び出されると一緒に破棄されます (これらのオブジェクトをブロックで作成iChannel
するsvcCon
ため) 。Sql.Dispose()
Sql
using
私のブロックがトリガーするSql.Dispose()
メソッドは次のusing
とおりです(重要な場合に備えて):
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(); }
}
要約すると、WCF 通信チャネルを作成しています。これにより、SqlConnection
. それを使用して、SQL 呼び出しを開始します。これらはすべて、可能な限り迅速に破棄されます。必要なデータベース操作を実行するために必要な期間を超えて、これらの接続に固執することはありません。そして、これらがブロック内で作成されていないという非常にまれなusing
ケースがあります。つまり、適切にクリーンアップしていると確信しています。もちろん、誰かが私のDispose()
方法に問題を見つけた場合を除きます。
アドバイスをいただければ幸いです。リクエストに応じて、より多くのコードを提供できます。
いくつかの追加情報: 以下 は、クライアントをデバッグし、サーバー コードにステップインして、返そうとしたときに何が起こるかを確認するときに受け取るスタック トレース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'