Lazy loading و Eager loading در C# و SQL

درسنامه درس 14 از سری آموزش LINQ

با سلام خدمت کاربران عزیز با یکی دیگر از سری آموزش های LINQ to SQL  در خدمت شما عزیزان هستیم در این جلسه قصد داریم تفاوت lazy loading و eager loading را مورد بررسی قرار دهیم.

Lazy loading و Eager loading چیست؟

در قسمت های قبلی آموزش گفتیم که هنگام اضافه کردن پایگاه داده و جداول به LINQ to SQL، از آن ها مدلی برای ما ساخته می شود و تمامی تغییرات بر روی مدل انجام می شود و وظیفه ی ترجمه ی کدهای C# به SQL  و اعمال آن روی پایگاه داده ی اصلی، بر عهده ی مدل می باشد. Lazy loading و Eager loading به دو نوع مختلف از فراخوانی کدهای C# به SQL توسط مدل گفته می شود که هر کدام مزایا و معایبی دارند. در ادامه با آن ها آشنا خواهیم شد.

لازم است برای انجام مراحل کار ابتدا جداولی مناسب ایجاد کرده و مانند قبل به مدل اضافه کنیم. می توانید جداول دلخواه خود را استفاده کنید یا دو جدول زیر را ایجاد  کنید:

جدول Employee
جدول Employee
جدول Department
جدول Department

توجه داشته باشید چون در اینجا قصد داریم تبدیل کدهای C# به SQL را توسط مدل بررسی کنیم لازم است جداول کمی پیچیده باشند برای همین فیلد Department_FK_ID از جدول Employee را کلید خارجی قرار دهید. در هر دو جدول فیلد ID از نوع Identity اعلام شده است. در این مورد لازم است ابتدا پروژه ای از نوع Console App ایجاد کنید و مانند جلسات قبلی پایکاه داده را به مدل اضافه کنید تا در نهایت شکل زیر حاصل شود.

مدل اصلی پایگاه داده
مدل اصلی پایگاه داده

توجه داشته باشید قبل از ادامه ی کار جداول را با اطلاعات مناسب پر کنید.

حالت اول: Lazy loading

اجازه دهید برای درک بهتر یک حالت ساده را در نظر بگیریم. ابتدا کدهای لازم را بنویسد تا با بررسی خروجی کد با Lazy loading آشنا شویم.

کدهای زیر به پروژه اضافه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            EmployeeModelDataContext context = new EmployeeModelDataContext();
            var res = context.Employees.Select(x => x.Firstname);
            context.Log = Console.Out;
            foreach (var item in res)
            {
                Console.WriteLine(item);
            }

        }
    }
}

مشابه این مثال را بارها در قسمت آموزش LINQ بررسی کردیم که با استفاده از متد Select نام رکوردهای موجود در جدول را نمایش داده ایم اما مهم ترین قسمت این کد context.Log = Console.Out است که در واقع کد ترجمه شده توسط LINQ را که به پایگاه داده ارسال می کند، نشان می دهد. برنامه را اجرا و با دقت بسیار خروجی را بررسی کنید.

خروجی کد
خروجی کد

به قسمت قرمز رنگ عکس بالا توجه کنید که یک کد SQL است که توسط مدل ایجاد شده و به پایگاه داده ارسال می شود.

حالا کد زیر را جایگزین کد قبلی کنید:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            EmployeeModelDataContext context = new EmployeeModelDataContext();
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            context.Log = Console.Out;
            foreach (Department dep in context.Departments)
            {
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine(dep.Name);
                Console.WriteLine();
                foreach (Employee emp in dep.Employees)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine(emp.Firstname+"\t"+emp.Gender);
                }
            }

        }
    }
}

در این مورد قصد داریم با استفاده از عنوان شغلی، رکوردهای جدول را بر اساس Firstname و Lastname دسته بندی کنیم ابتدا خط کد context.Log = Console.Out را کامنت و سپس برنامه را اجرا کنید تا یک دید کلی نسبت به خروجی پیدا کنید.

حالا برنامه را با خط context.Log = Console.Out اجرا کنید و خروجی را مشاهده کنید، ممکن است در نگاه اول کمی گیج کننده و نا مفهوم به نظر برسد پس اجازه دهید به بررسی آن بپردازیم:

خروجی کد
خروجی کد

می بینید که هر ردیف شغلی با کارمندانش نمایش داده شده است اما به تعداد Query هایی که مدل به سمت پایگاه داده فرستاده دقت کنید. Query زرد رنگ بر روی جدول Department زده شده تا فیلد مورد نظر ما که در اینجا Name است را چاپ کند اما به Query های سبز رنگ دقت کنید، می بینید که به تعداد رکوردهای موجود در جدول Department، به پایگاه داده درخواست ارسال شده است،

به عبارتی ما 3 ردیف شغلی برای این مثال در نظر گرفتیم که به ازای هر 3 مورد، Query به پایگاه داده ارسال کرده ایم به بیانی ساده تر در Lazy loading روند اجرای برنامه به صورت مرحله به مرحله است، یعنی تا زمانی که نیاز به ایجاد یک شئ نباشد آن شئ ایجاد نخواهد شد. این روش بیشتر برای برنامه نویسی وب با ASP.net کاربرد دارد.

زمانی را در نظر بگیرید که جدول شما 1000 رکورد دارد اگر تمامی رکورد ها قرار باشد یکجا و همزمان لود شوند ممکن است سایت با کندی آزار دهنده مواجه شود به همین دلیل بهتر است از Lazy loading استفاده شود تا همزمان با اسکرول کردن صفحه توسط کاربرد اطلاعاتی که در آن لحطه واقعا به آن ها نیاز است لود شوند.

حالت دوم: Eager loading

ابتدا لازم است کد زیر را به پروژه اضافه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Linq;
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            EmployeeModelDataContext context = new EmployeeModelDataContext();
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            context.Log = Console.Out;
            DataLoadOptions loadOptions = new DataLoadOptions();
            loadOptions.LoadWith<Department>(d => d.Employees);
            context.LoadOptions = loadOptions;
            foreach (Department dep in context.Departments)
            {
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine(dep.Name);
                Console.WriteLine();
                foreach (Employee emp in dep.Employees)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine(emp.Firstname+"\t"+emp.Gender);
                }
            }

        }
    }
}

این کد تا حدودی مشابه قسمت قبل بوده، فقط در این جا از کلاس DataLoadOptions استفاده کرده ایم که در فضای نام System.Data.Linq قرار دارد. بعد از ایجاد شی از این کلاس لازم است دیتای آن را مشخص کرده و در نهایت آن را به شئ مدل متصل کنیم. برنامه را اجرا کنید و خروجی را مشاهده کنید.

خروجی

می بینید که فقط با یک بار ارسال Query به پایگاه داده، اطلاعات را استخراج کرده ایم و در خروجی نمایش داده ایم. در مورد Lazy loading گفتیم که تا زمانی که نیاز به شئ نباشد آن شئ را تولید نمی کند اما در مورد Eager loading قضیه متفاوت است.

در این مورد ابتدا تمامی اشیا ساخته و مقدار دهی می شوند تا در جای مناسب از برنامه استفاده شوند.

دقیقا مانند شکل بالا که با یک بار ارسال Query تمامی اشیا و فیلدها مقدار دهی شده اند.

نتیجه گیری کلی

مبحث Lazy loading و Eager loading بسیار پیچیده بوده و دارای نکات بسیار مهمی است و کاربردهای بسیار فراوانی دارد که ذکر آنها در یک جلسه ممکن نیست هدف از این جلسه از آموزش، آشنایی کلی با این دو بود. به طور کلی استفاده از Lazy loading و Eager loading توسط برنامه نویس به نوع برنامه و کاربرد آن بستگی دارد مثلا برای برنامه های ویندوزی تحت وب در صورتی که با حجم زیادی از اطلاعات سروکار داشته باشیم بهتر است از Lazy loading استفاده شود در غیر این صورت ممکن است برنامه با مشکل مواجه شود. اما حالتی را در نظر بگیرید که قرار است داده هایی ثابت و کم حجم را از پایگاه داده بخوانید و همزمان در قسمت های مختلف از آن ها استفاده کنید (برنامه نویسی multithreading) در این حالت لازم است که اطلاعات به صورت همزمان لود و قابل دستیابی باشند پس از Eager loading استفاده خواهیم کرد تا برنامه به درستی اجرا و نیاز کاربر را برطرف سازد.

بررسی تفاوت lazy loading و eager loading نیز به پایان رسید دوستان عزیز توجه داشته باشید ک این بخش بیشتر جنبه ی آشنایی داشت تا آموزش برای بررسی دقیق تر این دو مبحث لازم است در LINQ و Entity Framework مهارت کافی داشته باشید.

موفق باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش LINQ توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

پرستو
18 بهمن 1399
سلام ممنون از توضیح و مثال خوبتون، برای من مشکلی پیش اومده این کد context.LoadOptions = loadOptions; در کد های من خطا دارد و وقتی اون رو کامنت میکنم دیگه نام کارمندان رو نشون نمیده و فقط نام دپارتمان ها نمایش داده میشه کد ها هم دقیقا مثل کد های شماست. اگه میشه لطفا راهنماییم کنید.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.