NInject和多线程问题

时间:2013-01-11 21:32:35

标签: c# multithreading entity-framework ninject

我们正在使用实体框架4作为我们的Web应用程序,将Ninject作为我的DI容器。我们有一个日志表来记录我们的应用程序中发生的所有事情,我们还有后端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异常,   Boolean breakConnection)at   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()at   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,   SqlCommand cmdHandler,SqlDataReader dataStream,   BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject   stateObj)at   System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(字节[]   buffer,TransactionManagerRequestType请求,String 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)at   System.Data.SqlClient.SqlInternalConnection.BeginTransaction(的IsolationLevel   iso)at   System.Data.SqlClient.SqlConnection.BeginDbTransaction(的IsolationLevel   isolationLevel)at   System.Data.EntityClient.EntityConnection.BeginDbTransaction(的IsolationLevel   的IsolationLevel)

我知道我可以使用“using”语句创建新的上下文并写入ti日志表而不会出现任何问题。但我不想这样做,因为这会使一切变慢,然后在threadscope中创建Context。

处理这种情况的最佳方法是什么?我需要执行时间最短的实现。

如果您需要更多信息,请发表评论。提前谢谢。

1 个答案:

答案 0 :(得分:1)

你应该听Daniel的评论。 NLog和Log4Net是更好的选择。

我不建议像Jalalx提到的那样锁定db,因为如果你有很多日志,它最终可能会减慢锁的执行速度。如果你没有写日志,那么一定要试一试。

两个选项 -

  1. 按照线程注册您的数据库连接/上下文 - 然后您不必担心跨线程共享,它不会发生。
  2. 创建一个“DbConnectionFactory”,创建可在每个线程/执行的上下文中调用的db连接/上下文。
  3. 所以基本上它要么让Ninject管理它,要么创建一个抽象,以便你自己管理它。

    顺便说一下,对于.NET来说,不是最慢的DI框架吗?