1

Web アプリケーションに Entity Framework 4 を使用し、DI コンテナーとして Ninject を使用しています。アプリケーションで発生したすべてをログに記録するためのログ テーブルがあり、ログを再びログ テーブルに書き込むバックエンド WCF ワークフロー サービスもあります。

私たちが使用するウェブからのすべてのリクエストに対して

StandardScopeCallbacks.Request(ctx);

そして、私たちが使用するバックエンドのすべてのために

StandardScopeCallbacks.ThreadScope(ctx);

ロギング方法は非常にシンプルです

 public void Log(string message, LogLevel level)
        {
             var log = new ApplicationLog()
                    {
                        LogDate = DateTime.Now,
                        Message = message,
                        LogLevel = Enum.GetName(typeof(LogLevel), level)
                    };

                    db.ApplicationLog.Add(log);
                    db.SaveChanges();          
        }

問題 : より多くのスレッドが実行されている場合、例外が発生します

System.Data.SqlClient.SqlException: セッションで他のスレッドが実行されているため、新しいトランザクションは許可されません。で

System.Data.SqlClient.SqlConnection.OnError(SqlException 例外、ブール型 breakConnection) で System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() で System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet bulkCopyHandler 、TdsParserStateObject stateObj) で System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] バッファー、TransactionManagerRequestType リクエスト、文字列 transactionName、TransactionManagerIsolationLevel isoLevel、Int32 タイムアウト、SqlInternalTransaction トランザクション、TdsParserStateObject stateObj、ブール値 isDelegateControlRequest) で

System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon (TransactionRequest transactionRequest、String transactionName、IsolationLevel iso、SqlInternalTransaction internalTransaction、Boolean isDelegateControlRequest) で

System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso、String transactionName) で System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso) で System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel) で System.Data.EntityClient .EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)

「using」ステートメントを使用して新しいコンテキストを作成し、ログテーブルに問題なく書き込むことができることはわかっています。しかし、スレッドスコープでコンテキストを作成するよりもすべてが遅くなるため、これを行いたくありません。

このようなシナリオを処理する最善の方法は何ですか? 実行時間が最小になる実装が必要です。

さらに情報が必要な場合は、コメントを残してください。前もって感謝します。

4

1 に答える 1

1

ダニエルのコメントに耳を傾けるべきです。NLog と Log4Net はより良いオプションです。

Jalalx が述べたように db をロックすることはお勧めしません。多くのログがある場合、ロックの周りで実行が遅くなる可能性があるためです。ログへの大量の書き込みがない場合は、ぜひ試してみてください。

2 つのオプション --

  1. スレッドごとにデータベース接続/コンテキストを登録します。クロススレッド共有について心配する必要はありません。それは起こりません。
  2. 各スレッド/実行のコンテキスト内で呼び出すことができるデータベース接続/コンテキストを作成する「DbConnectionFactory」を作成します。

したがって、基本的には、Ninject に管理させるか、自分で管理できるように抽象化を作成します。

ところで、ninject は .NET 用の最も遅い DI フレームワークではありませんか?

于 2013-01-12T03:16:30.733 に答える