یک نکتهی تکمیلی: معادل این مطلب با EF Core 5x
کدهای Interceptor به این صورت اصلاح شده و تطابق خواهند یافت:
using System;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Logging;
namespace Utils
{
public class EfExceptionsInterceptor : DbCommandInterceptor
{
private readonly ILogger<EfExceptionsInterceptor> _logger;
public EfExceptionsInterceptor(ILogger<EfExceptionsInterceptor> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)
{
logError(command, eventData);
}
public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)
{
logError(command, eventData);
return Task.CompletedTask;
}
private void logError(DbCommand command, CommandErrorEventData eventData)
{
if (command == null || eventData == null)
{
return;
}
var ex = eventData.Exception;
if (ex == null)
{
return;
}
var sqlData = logSqlAndParameters(command);
var contextualMessage = $"{sqlData}{Environment.NewLine}OriginalException:{Environment.NewLine}{ex} {Environment.NewLine}";
_logger.LogError(contextualMessage);
}
private static string logSqlAndParameters(DbCommand command)
{
// -- Name: [Value] (Type = {}, Direction = {}, IsNullable = {}, Size = {}, Precision = {} Scale = {})
var builder = new StringBuilder();
var commandText = command.CommandText ?? "<null>";
builder.AppendFormat(CultureInfo.InvariantCulture, "{0}Command: {0}{1}", Environment.NewLine, commandText)
.AppendLine();
var parameters = command.Parameters.OfType<DbParameter>().ToList();
if (parameters.Any())
{
builder.AppendFormat(CultureInfo.InvariantCulture, "{0}Parameters: ", Environment.NewLine)
.AppendLine();
}
foreach (var parameter in parameters)
{
builder.Append("-- ")
.Append(parameter.ParameterName)
.Append(": '")
.Append((parameter.Value == null || parameter.Value == DBNull.Value) ? "null" : parameter.Value)
.Append("' (Type = ")
.Append(parameter.DbType);
if (parameter.Direction != ParameterDirection.Input)
{
builder.Append(", Direction = ").Append(parameter.Direction);
}
if (!parameter.IsNullable)
{
builder.Append(", IsNullable = false");
}
if (parameter.Size != 0)
{
builder.Append(", Size = ").Append(parameter.Size);
}
if (((IDbDataParameter)parameter).Precision != 0)
{
builder.Append(", Precision = ").Append(((IDbDataParameter)parameter).Precision);
}
if (((IDbDataParameter)parameter).Scale != 0)
{
builder.Append(", Scale = ").Append(((IDbDataParameter)parameter).Scale);
}
builder.Append(')').Append(Environment.NewLine);
}
return builder.ToString();
}
}
}
سپس برای ثبت آن، چون یک سرویس را به صورت تزریق وابستگیها دریافت کرده، یکبار باید آنرا به سیستم تزریق وابستگیها معرفی کرد:
services.AddScoped<EfExceptionsInterceptor>();
و بعد نحوهی معرفی آن به AddDbContextPool به روش خاص زیر است که از سرویسپروایدر استفاده میکند:
services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
optionsBuilder
.UseSqlServer(
connectionString,
sqlServerOptionsBuilder =>
{
// ...
})
.AddInterceptors(serviceProvider.GetRequiredService<EfExceptionsInterceptor>()));
این نکتهای است که جهت ثبت Interceptorهای دارای تزریق وابستگی، مورد استفاده قرار میگیرد.