【发布时间】:2012-12-26 13:19:45
【问题描述】:
我们将 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 异常, 布尔中断连接)在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler、SqlDataReader 数据流、 BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(字节 [] 缓冲区,TransactionManagerRequestType 请求,字符串 transactionName, TransactionManagerIsolationLevel isoLevel,Int32 超时, SqlInternalTransaction 事务,TdsParserStateObject stateObj, Boolean isDelegateControlRequest) 在
System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest,字符串 transactionName,IsolationLevel iso, SqlInternalTransaction 内部事务,布尔值 isDelegateControlRequest) 在
System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso,字符串事务名称)在 System.Data.SqlClient.SqlInternalConnection.BeginTransaction(隔离级别 异)在 System.Data.SqlClient.SqlConnection.BeginDbTransaction(隔离级别 隔离级别)在 System.Data.EntityClient.EntityConnection.BeginDbTransaction(隔离级别 隔离级别)
我知道我可以使用“使用”语句创建新上下文并编写 ti Log 表而不会出现任何问题。但我不想这样做,因为这会使一切变得比在线程范围中创建上下文更慢。
处理这种情况的最佳方法是什么?我需要执行时间最短的实现。
如果您需要更多信息,请发表评论。提前谢谢你。
【问题讨论】:
-
变量db从何而来?它是否注入到您的 Log 方法所在的任何类的构造函数中? db 是你的 EF 上下文吗?
-
我希望你很清楚每个主要的日志框架都有附加程序,它们直接写入你选择的数据库。为什么要重新发明轮子?还请提供更多背景信息,以便我们为您提供帮助
-
您是否在
Log方法中尝试过lock(db){ ... }? -
感谢大家的cmets。我知道我们可以使用日志框架并摆脱所有问题。但是我们需要这个来进行中间修复。是的 db 是 EF 上下文并从 jInject 注入。
-
I can you lock(db){..} and using(var db = new DBContext()) {...}.. 但我仍然想使用为我创建的相同上下文线程使用 Ninject。
标签: c# multithreading entity-framework ninject