ثبت جزئیات استثناهای Entity framework توسط ELMAH

entity-framework-exceptional-detail-by-elmah
وبلاگآموزشبرنامه نویسیثبت جزئیات استثناهای Entity framework توسط ELMAH

در حین بروز استثناهای Entity framework، می‌توان توسط ابزارهای Logging متنوعی مانند ELMAH، جزئیات متداول آن‌ها را برای بررسی‌های آتی ذخیره کرد. اما این جزئیات فاقد SQL نهایی تولیدی و همچنین پارامترهای ورودی توسط کاربر یا تنظیم شده توسط برنامه هستند. برای اینکه بتوان این جزئیات را نیز ثبت کرد، می‌توان یک IDbCommandInterceptor جدید را طراحی کرد.

کلاس EfExceptionsInterceptor

در اینجا نمونه‌ای از یک پیاده سازی اینترفیس IDbCommandInterceptor را مشاهده می‌کنید. همچنین طراحی یک متد عمومی که می‌تواند به جزئیات SQL نهایی و پارامترهای آن دسترسی داشته باشد، در اینترفیس IEfExceptionsLogger ذکر شده‌است

public interface IEfExceptionsLogger
{
void LogException<TResult>(DbCommand command,
DbCommandInterceptionContext<TResult> interceptionContext);
}

using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;

namespace ElmahEFLogger
{
public class EfExceptionsInterceptor : IDbCommandInterceptor
{
private readonly IEfExceptionsLogger _efExceptionsLogger;

public EfExceptionsInterceptor(IEfExceptionsLogger efExceptionsLogger)
{
_efExceptionsLogger = efExceptionsLogger;
}

public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}

public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}

public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}

public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}

public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}

public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
_efExceptionsLogger.LogException(command, interceptionContext);
}
}
}

تهیه یک پیاده سازی سفارشی از IEfExceptionsLogger توسط ELMAH

اکنون که ساختار کلی IDbCommandInterceptor سفارشی برنامه مشخص شد، می‌توان پیاده سازی خاصی از آن‌را جهت استفاده از ELMAH به نحو ذیل ارائه داد:

using System;
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using Elmah;

namespace ElmahEFLogger.CustomElmahLogger
{
public class ElmahEfExceptionsLogger : IEfExceptionsLogger
{
/// <summary>
/// Manually log errors using ELMAH
/// </summary>
public void LogException<TResult>(DbCommand command,
DbCommandInterceptionContext<TResult> interceptionContext)
{
var ex = interceptionContext.OriginalException;
if (ex == null)
return;

var sqlData = CommandDumper.LogSqlAndParameters(command, interceptionContext);
var contextualMessage = string.Format(“{0}{1}OriginalException:{1}{2} {1}”, sqlData, Environment.NewLine, ex);

if (!string.IsNullOrWhiteSpace(contextualMessage))
{
ex = new Exception(contextualMessage, new ElmahEfInterceptorException(ex.Message));
}

try
{
ErrorSignal.FromCurrentContext().Raise(ex);
}
catch
{
ErrorLog.GetDefault(null).Log(new Error(ex));
}
}
}
}

در اینجا شیء Command به همراه SQL نهایی تولید و پارامترهای مرتبط است. همچنین interceptionContext.OriginalException جزئیات عمومی استثنای رخ داده را به همراه دارد. می‌توان این اطلاعات را پس از اندکی نظم بخشیدن، به متد Raise مربوط به ELMAH ارسال کرد تا جزئیات بیشتری از استثنای رخ داده شده، در لاگ‌های آن ظاهر شوند.

استفاده از ElmahEfExceptionsLogger جهت طراحی یک Interceptor عمومی

public class ElmahEfInterceptor : EfExceptionsInterceptor
{
public ElmahEfInterceptor()
: base(new ElmahEfExceptionsLogger())
{ }
}

برای استفاده از ElmahEfExceptionsLogger و تهیه یک Interceptor عمومی، می‌توان با ارث بری از کلاس Interceptor ابتدای بحث شروع کرد و وهله‌ای از ElmahEfExceptionsLogger را به سازنده‌ی آن تزریق نمود (یکی از چندین روش ممکن). سپس برای استفاده از آن کافی است به ابتدای متد Application_Start فایل Global.asax.cs مراجعه و در ادامه سطر ذیل را اضافه نمود:

DbInterception.Add(new ElmahEfInterceptor());

پس از آن جزئیات کلیه استثناهای EF در لاگ‌های نهایی ELMAH به نحو ذیل ظاهر خواهند شد:

entity framework exceptional detail by elmah 2 - ثبت جزئیات استثناهای Entity framework توسط ELMAH

entity framework exceptional detail by elmah - ثبت جزئیات استثناهای Entity framework توسط ELMAH

web based version of whatsapp - ثبت جزئیات استثناهای Entity framework توسط ELMAH