mud*_*ess 12 c# entity-framework nlog
我们正在运行Entity Framework 6并且有一个DatabaseLogFormatter来格式化我们的数据,它通过NLog AsyncTargetWrapper记录到一个文件中.该应用程序是一个MVC5 Web应用程序.
DatabaseLogFormatter主要是空的存根,LogCommand和LogResult除外.两者都正确地格式化数据.到目前为止,NLog日志记录一直没有问题.
我们遇到的问题是,经过几个小时的正常运行时间(似乎是随机的,无法找到模式),它将创建几乎重复的日志行.一旦启动它继续记录每一行两次或三次.有时它会随机返回一行.
行将在DatabaseLogFormatter中读取的时间不同,这意味着请求正在重新格式化(而不是NLog问题).
public class NLogFormatter : DatabaseLogFormatter
{
private static readonly DbType[] StringTypes = { DbType.String, DbType.StringFixedLength, DbType.AnsiString, DbType.AnsiStringFixedLength, DbType.Date, DbType.DateTime, DbType.DateTime2, DbType.Time, DbType.Guid, DbType.Xml};
public NLogFormatter(DbContext context, Action<string> writeAction)
: base(context, writeAction)
{
}
public override void LogCommand<TResult>(
DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{
var builder = new StringBuilder();
builder.Append($"COMMAND|{(command.CommandType == CommandType.StoredProcedure ? "EXEC " :"")}{command.CommandText.Replace(Environment.NewLine, " ")} ");
foreach (var parameter in command.Parameters.OfType<DbParameter>())
{
builder.Append("@")
.Append(parameter.ParameterName)
.Append(" = ")
.Append(parameter.Value == null || parameter.Value == DBNull.Value ? "null" : StringTypes.Any(t => t == parameter.DbType) ? $"'{parameter.Value}'" : parameter.Value);
builder.Append(", ");
}
Write(builder.ToString());
}
public override void LogResult<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{
var sw = Stopwatch;
Write($"COMPLETED|{command.CommandText.Replace(Environment.NewLine, " ")}|{sw.ElapsedMilliseconds}ms");
}
//rest removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
和EF上下文(来自DB第一模型).DB调用是使用未修改的EF生成函数进行的,我们主要使用存储过程.
public class EfDbConfiguration : DbConfiguration
{
public EfDbConfiguration()
{
SetDatabaseLogFormatter((context, action) => new NLogFormatter(context, action));
}
}
public class EfFunctions
{
private readonly EfEntities _db = new EfEntities { Database = { Log = Logger.LogEfRequest } };
//Function calls etc
}
Run Code Online (Sandbox Code Playgroud)
日志输出如何显示的示例
2017-10-22 23:47:22.0611|Debug|REQUEST|Example.Page|POST|/example/page
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.0611|Debug|DB|COMMAND|EXEC [Test].[GetOrder] @OrderNumber = '123456789', @ErrorCode = null,
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|DB|COMPLETED|[Test].[GetOrder]|149ms
2017-10-22 23:47:22.2111|Debug|APP|No order or session, creating new session|123456789
Run Code Online (Sandbox Code Playgroud)
Cataklysim 的评论指出了正确的方式。
问题是请求链的所有部分的处理不正确,DbContext 对象未处理时存在不匹配,即使创建了新的 DbContext(以及新的记录器),现有记录器仍保持活动状态,然后两者都会捕获事件并记录。测试时它没有在本地显示,因为服务器需要时间来旋转和启动新线程以创建多个 DbContext。
确保手动处置一次性物品(并确保处置整个链)或使用在块末尾调用 Dispose 的Using(Disposable)。
归档时间: |
|
查看次数: |
630 次 |
最近记录: |