1

我们将 Entity framework 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 异常,布尔 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, Boolean isDelegateControlRequest) 在

System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest,字符串 transactionName,IsolationLevel iso,SqlInternalTransaction internalTransaction,布尔 isDelegateControlRequest)在

System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName) 在 System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso) 在 System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevelisolationLevel) 在 System.Data.EntityClient .EntityConnection.BeginDbTransaction(IsolationLevel 隔离级别)

我知道我可以使用“使用”语句创建新上下文并编写 ti Log 表而不会出现任何问题。但我不想这样做,因为这会使一切变得比在线程作用域中创建上下文更慢。

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

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

4

1 回答 1

1

You should listen to Daniel's comment. NLog and Log4Net are better options.

I would not recommend locking on db as Jalalx mentioned, because it could end up slowing execution around the locks if you have a lot of logs. If you don't have a ton writing to logs, then sure give it a try.

Two options--

  1. Register your db connection/context as per thread -- then you don't have to worry about cross- thread sharing, it won't happen.
  2. Create a "DbConnectionFactory" that creates db connections/contexts that you can call within the context of each thread/execution.

So basically its either let Ninject manage it, or create an abstraction so that you can manage it yourself.

Btw, isn't ninject the slowest DI framework out there for .NET?

于 2013-01-12T03:16:30.733 回答