گاهی اوقات ممکن است کوئری هایی را در EF بنویسیم و دیتای زیادی را از دیتابیس فراخوانی کنیم و با بزرگ تر شدن پروژه تعداد کوئری ها نیز افزایش می یابد در نتیجه پیداکردن کوئری های سنگین سخت و یا غیرممکن میشود. اگر در SQL Profiler نیز این کوئری ها را بدست بیاورید تقریبا غیر ممکن است که بتوانید کوئری نوشته شده معادل EF آن را در کدهای خود پیدا کنید. در EF Core 2.2 قابلیت جدیدی به نام WithTag به کوئری های EF اضافه شده است که میتوان به کوئری ها یک برچسب زد و این برچسب به همراه کوئری به سمت SQL ارسال میشود و زمانی که به SQL Profiler نگاه کنید برچسب استفاده شده برای کوئری را نیز مشاهده میکنید که این کار باعث میشود آسان تر کوئری های نوشته شده در EF را پیدا کرد. این قابلیت باعث  میشود ارتباط بهتری بین DBA و برنامه نویس ایجاد شود و بتوان کوئری هایی که اشتباه نوشته شده اند و یا دیتای زیادی را از دیتابیس میخوانند را راحت تر پیدا کرد و عملا زودتر میتوان مشکل را حل کرد. این قابلیت به صورت یک اسکتنشن متد به EF Core استفاده شده است که به صورت زیر قابل استفاده است.

var result = await _context.Blogs
    .Where(i => i.Url.StartsWith("http://dotnetdocs.ir"))
    .TagWith("Looking for dotnetdocs.ir")
    .ToListAsync();

اکنون اگر کوئری بالا اجرا شود خروجی زیر را میتوان از SQL Profiler دریافت کرد.

-- Looking for dotnetdocs.ir

SELECT [b].[Id], [b].[Url]
FROM [Blogs] AS [b]
WHERE [b].[Url] IS NOT NULL AND ([b].[Url] LIKE N'http://dotnetdocs.ir%')

با این کار راحت تر میتوان به کوئری ها دسترسی پیدا کنیم. اما میتوان دقیقتر هم باشد. با استقاده از Caller Attribute ها میتوان دقیقا محل اجرای کدها را بدست آورد. برای این کار یک اکستنش متد نوشته ایم که سه ویژگی مسیر فایل, شماره خط و نام متد را همراه با برچسب به SQL ارسال میکند.

public static IQueryable<T> TagWithSource<T>(
    this IQueryable<T> queryable,
    [CallerLineNumber] int lineNumber = 0,
    [CallerFilePath] string filePath = "",
    [CallerMemberName] string memberName = "")
{
    return queryable.TagWith($"{memberName}  - {filePath}:{lineNumber}");
}
public static IQueryable<T> TagWithSource<T>(this IQueryable<T> queryable,
    string tag,
    [CallerLineNumber] int lineNumber = 0,
    [CallerFilePath] string filePath = "",
    [CallerMemberName] string memberName = "")
{
    return queryable.TagWith($"{tag}{Environment.NewLine}{memberName}  - {filePath}:{lineNumber}");
}

اکنون اگر مجددا کوئری را اجرا کنید:

class Program
{
    static void Main(string[] args)
    {
        using (ApplicationDbContext dbContext = new ApplicationDbContext())
        {
            var data = dbContext.Blogs
                .Where(i => i.Url.StartsWith("http://dotnetdocs.ir"))
                .TagWithSource("Looking for dotnetdocs.ir")
                .ToListAsync();
        }
    }
}

 اطلاعات زیر را در SQL Profiler مشاهده میکنید.

-- Looking for dotnetdocs.ir
-- Main  - C:\Users\Farhad\source\repos\TaggingWithEFCore\TaggingWithEFCore.ConsoleApplication\Program.cs:17

SELECT [b].[Id], [b].[Url]
FROM [Blogs] AS [b]
WHERE [b].[Url] IS NOT NULL AND ([b].[Url] LIKE N'http://dotnetdocs.ir%')

;)

Powered by Froala Editor