LINQ in C# tutorial

LINQ در C# چیست؟ آموزش کامل Language Integrated Query از صفر تا پیشرفته

مقدمه

اگر تاکنون با حلقه‌های foreach، for یا جستجو در لیست‌ها کار کرده باشید، احتمالاً با کدهایی شبیه این مواجه شده‌اید:

foreach(var user in users)
{
    if(user.Age > 18)
    {
        ...
    }
}

حالا تصور کنید بتوانید همین کار را تنها با یک خط کد انجام دهید:

var adults = users.Where(x => x.Age > 18);

اینجاست که LINQ وارد بازی می‌شود.

LINQ یا Language Integrated Query یکی از قدرتمندترین قابلیت‌های زبان C# است که به شما اجازه می‌دهد داده‌ها را بدون نوشتن حلقه‌های پیچیده، فیلتر، مرتب، گروه‌بندی و پردازش کنید.

در این مقاله با LINQ از پایه آشنا می‌شویم و مهم‌ترین قابلیت‌های آن را بررسی می‌کنیم.

LINQ چیست؟

تکنولوژی LINQ قابلیتی در دات‌نت است که به توسعه‌دهندگان اجازه می‌دهد تا با استفاده از یک ساختار یکپارچه، خوانا و شبیه به SQL، مستقیماً درون کدهای سی‌شارپ (C#) از انواع منابع داده مانند لیست‌ها، دیتابیس‌ها و XML کوئری بگیرند.این قابلیت برای اولین بار در سال ۲۰۰۷ به همراه نسخه C# 3.0 و دات‌نت فریم‌ورک 3.5 به دنیای برنامه‌نویسی معرفی شد.مایکروسافت آن را ساخت تا شکاف میان زبان‌های برنامه‌نویسی شیءگرا (مثل C#) و پایگاه‌های داده (مثل SQL) را از بین ببرد، از نوشتن کدهای تکراری (Iterative) جلوگیری کند و خطایابی و خوانایی کدها را به شدت افزایش دهد.

چرا باید LINQ را یاد بگیریم؟

کاهش کدهای تکراری: با LINQ نیازی به نوشتن حلقه‌های پیچیده for و foreach و منطق‌های فیلترینگ دستی ندارید و حجم کدها به شدت کاهش می‌یابد.

خوانایی بالا و نگهداری آسان: کوئری‌ها ساختاری شبیه به زبان انسانی و SQL دارند که باعث می‌شود خواندن و درک کدها برای سایر برنامه‌نویسان بسیار ساده‌تر شود.

امنیت نوع داده‌ها (Type Safety): برخلاف کوئری‌های متنی SQL که خطاهای آن‌ها تنها در زمان اجرای برنامه مشخص می‌شود، خطاهای LINQ در زمان کامپایل (Compile-time) شناسایی می‌شوند.

پشتیبانی از IntelliSense: امکانات کامل تکمیل خودکار کد در IDE (مثل Visual Studio) به شما کمک می‌کند تا سریع‌تر و با خطای کمتری کد بزنید.

یکپارچگی با منابع مختلف: با یک دستور زبان واحد می‌توانید به منابع داده گوناگون مثل لیست‌های درون حافظه، دیتابیس‌ها (از طریق Entity Framework) و فایل‌های XML متصل شوید.

LINQ چگونه کار می‌کند؟


List و Array: روی مجموعه‌های در حافظه (In-Memory) با استفاده از IEnumerable کار می‌کنند و عملیات پردازش داده‌ها مستقیماً در رم سیستم انجام می‌شود.

Dictionary و HashSet: این ساختارها نیز از طریق اینترفیس‌های مجموعه یا IEnumerable پشتیبانی می‌شوند و LINQ امکان جستجو و فیلتر سریع را روی کلیدها یا مقادیر آن‌ها فراهم می‌کند.

IEnumerable: پایه و اساس LINQ به صورت LINQ to Objects است. وقتی از IEnumerable استفاده می‌کنید، عملیات به صورت Deferred Execution (اجرای به تعویق افتاده) و در حافظه رم پردازش می‌شوند.

IQueryable: این حالت برای کار با منابع داده خارجی مثل دیتابیس‌ها (از طریق Entity Framework) طراحی شده است. دستورات LINQ به جای اجرا در حافظه، به کوئری‌های پایگاه داده (مثل SQL) ترجمه شده و مستقیماً روی سرور دیتابیس اجرا می‌شوند تا تنها داده‌های لازم به سمت اپلیکیشن ارسال شوند.

انواع LINQ :

نوع LINQکاربرد اصلیتوضیحات تکمیلی
LINQ to Objectsمجموعه‌ها (Collections) و آرایه‌ها در حافظهبرای کار با انواع List، Array، Dictionary و سایر مجموعه‌های در حال اجرا در حافظه RAM.
LINQ to SQLپایگاه داده SQL Serverابزاری سبک برای ارتباط مستقیم با دیتابیس‌های SQL Server و تبدیل دستورات به T-SQL (نسخه قدیمی‌تر قبل از EF).
LINQ to XMLفایل‌ها و داده‌های XMLبرای ایجاد، خواندن، دستکاری و جستجوی ساختارهای XML با سرعت و خوانایی بالا.
Entity Framework LINQانواع دیتابیس‌ها (Database)استاندارد مدرن دات‌نت برای اتصال به انواع دیتابیس‌ها (SQL Server، PostgreSQL، MySQL و…) از طریق ORM.
Parallel LINQ (PLINQ)پردازش موازی و سنگیننسخه موازی‌سازی شده LINQ که از تمام هسته‌های پردازنده (CPU) برای پردازش سریع‌تر داده‌های حجیم استفاده می‌کند.

انواع روش های نوشتن LINQ :

در این بخش به دو روش اصلی نوشتن کوئری‌های LINQ یعنی Method Syntax و Query Syntax می‌پردازیم و آن‌ها را با یکدیگر مقایسه می‌کنیم:

۱. روش Method Syntax (سینتکس متد)

در این روش از متدهای الحاقی (Extension Methods) و عبارت‌های لامبدا (Lambda Expressions) استفاده می‌شود. این روش به دلیل شباهت به برنامه‌نویسی تابعی، محبوب‌ترین و پرکاربردترین روش بین برنامه‌نویسان C# است.

var result = users.Where(x => x.Age > 18);

۲. روش Query Syntax (سینتکس کوئری)

این روش بسیار شبیه به زبان SQL است و از کلمات کلیدی مشخصی (مانند from, where, select) استفاده می‌کند. ساختار آن به صورت Declarative (بیانی) است.

var result = from user in users
             where user.Age > 18
             select user;

مهم‌ترین متدهای LINQ :

متدکاربرد
Whereفیلتر
Selectانتخاب کردن
SelectManyتخت کردن
OrderByمرتب سازی
GroupByگروه بندی کردن
Distinctحذف تکراری
Anyبررسی وجود
Allبررسی همه
Countشمارش
Firstگرفتن اولین آیتم که با شرط ما سازگار است اگه نباشد Exception میدهد.
FirstOrDefaultگرفتن اولین آیتم که با شرط ما سازگار است اگه نباشد مقدار پیش فرض را برمی گرداند.
Singleچک کردن وجود یک آیتم منحصر به فرد مانند کد ملی در صورت تکراری بودن Exception می دهد.
SingleOrDefaultچک کردن وجود یک آیتم منحصر به فرد مانند کد ملی در صورت تکراری بودن مقدار پیش فرض می دهد.

مثال عملی از LINQ :

برای درک بهتر نحوه کار با LINQ، فرض کنید یک کلاس Product به شکل زیر داریم:

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
}

حالا یک لیست نمونه از این محصولات داریم و می‌خواهیم چند عملیات رایج را با استفاده از LINQ انجام دهیم:

var products = new List<Product>
{
    new Product { Name = "Laptop", Price = 1200, Stock = 5 },
    new Product { Name = "Mouse", Price = 25, Stock = 50 },
    new Product { Name = "Keyboard", Price = 80, Stock = 0 },
    new Product { Name = "Monitor", Price = 300, Stock = 12 }
};

چند نمونه کوئری کاربردی با LINQ:

۱. فیلتر کردن (فقط محصولات موجود که قیمتشان زیر ۱۰۰ است):

var cheapProducts = products.Where(p => p.Price < 100 && p.Stock > 0);

۲. مرتب‌سازی (مرتب کردن محصولات بر اساس قیمت از زیاد به کم):

var sortedProducts = products.OrderByDescending(p => p.Price);

۳. انتخاب فیلدهای خاص (فقط استخراج نام محصولات):

var productNames = products.Select(p => p.Name);

۴. شرط‌های تجمیعی (بررسی اینکه آیا محصولی با موجودی صفر وجود دارد یا خیر):

bool outOfStockExists = products.Any(p => p.Stock == 0);

مزایای LINQ :

خوانایی بالا: ساختار یکپارچه و شبه‌کد LINQ باعث می‌شود کدهای فیلترینگ و جستجو به زبان انسان نزدیک‌تر شده و خواندن منطق برنامه برای سایر توسعه‌دهندگان بسیار ساده‌تر شود.

Performance مناسب: LINQ با بهینه‌سازی کوئری‌ها (مخصوصاً در IQueryable) و ارسال پردازش‌ها به سمت دیتابیس یا استفاده از مکانیزم‌های کش داخلی، کارایی مناسبی ارائه می‌دهد.

Type Safety (ایمنی نوع داده‌ها): برخلاف رشته‌های متنی SQL که خطاهای آن‌ها در زمان اجرا ظاهر می‌شوند، خطاهای سینتکسی و نام‌گذاری در LINQ در همان مرحله کامپایل (Compile-time) شناسایی و برطرف می‌شوند.

پشتیبانی کامل از IntelliSense: به لطف ویژگی‌های ساختاریافته در C#، محیط‌های توسعه (مانند Visual Studio) پیشنهادهای خودکار و کامل کد را حین تایپ کوئری‌ها ارائه می‌دهند که سرعت توسعه را افزایش می‌دهد.

نگهداری آسان (Maintainability): به دلیل حذف کدهای تکراری، حلقه‌های طولانی تو در تو و یکپارچه‌سازی منطق داده‌ها، تغییر، توسعه و رفع باگ کدهای برنامه‌نویسی بسیار آسان‌تر خواهد بود.

معایب LINQ :

LINQ همیشه سریع‌ترین راه نیست: در پردازش‌های بسیار سنگین یا حلقه‌های حجیم (در مقیاس میلیونی)، سربار ایجاد متدهای الحاقی و عبارت‌های لامبدا می‌تواند نسبت به یک حلقه ساده for یا foreach سنتی زمان بیشتری مصرف کند و حافظه (Memory Allocation) بیشتری درگیر سازد.

کاهش Performance در کدهای Deferred Execution (تنبلی در اجرا): مکانیزم اجرای به تعویق افتاده در LINQ اگر به درستی مدیریت نشود، ممکن است باعث اجرای مکرر و ناخواسته کوئری‌ها روی دیتابیس یا مجموعه‌ها شود که افت شدید کارایی را به همراه دارد.

افت شدید خوانایی در کوئری‌های پیچیده: برخلاف تصور عمومی، اگر یک کوئری LINQ بسیار طولانی شود و شامل چندین Join، GroupBy و شرط‌های تو در تو باشد، خواندن و دیباگ کردن آن به مراتب سخت‌تر از یک متد سنتی یا کوئری ساختاریافته خواهد شد.

مشکلات پنهان در ترجمه به SQL (توسط EF): گاهی اوقات نوشتن کوئری‌های پیچیده با LINQ باعث می‌شود که Entity Framework یک کوئری SQL بسیار سنگین، غیربهینه و کند (مثلاً با JOINهای اضافی یا عدم استفاده صحیح از Indexها) تولید کند که تشخیص آن نیاز به ابزارهای مانیتورینگ دارد.

تفاوت LINQ و SQL :


LINQSQL
داخل C#داخل Database
Type SafeText
IntelliSenseندارد

تفاوت Ienumerable و Iqueryable :

حوزه فعالیت (Execution):

  • IEnumerable روی داده‌های داخل حافظه رم (In-Memory) مانند List و Array کار می‌کند (طبیعت LINQ to Objects).
  • IQueryable برای کار با منابع داده خارجی مثل دیتابیس‌ها (از طریق Entity Framework) طراحی شده است.

نحوه بارگذاری داده‌ها (Data Loading):

  • در IEnumerable تمام داده‌ها ابتدا از دیتابیس یا منبع به حافظه رم منتقل می‌شوند و سپس فیلترینگ و عملیات روی آن‌ها انجام می‌گیرد.
  • در IQueryable عملیات فیلترینگ و شرط‌ها مستقیماً به کوئری SQL تبدیل شده و روی سرور دیتابیس اجرا می‌شوند تا فقط داده‌های نهایی به اپلیکیشن برسند.

پشتیبانی از Deferred Execution پیشرفته:

  • هر دو از اجرای به تعویق افتاده پشتیبانی می‌کنند، اما IQueryable قابلیت Expression Trees را دارد؛ یعنی منطق کد شما را می‌خواند، آن را به دستورات پایگاه داده ترجمه می‌کند و بهینه‌تر عمل می‌کند.

آیا LINQ سرعت برنامه را کم می‌کند؟


بله، در شرایط خاصی می‌تواند تأثیر منفی بگذارد. همان‌طور که اشاره شد، در حلقه‌های بسیار بزرگ و پردازش‌های سنگین روی داده‌های در حافظه، سربار متدهای الحاقی (Extension Methods) و ساختار LINQ ممکن است از یک حلقه سنتی foreach کندتر عمل کند. همچنین اگر کوئری‌های LINQ به درستی به دیتابیس ترجمه نشوند، می‌توانند کوئری‌های سنگین و غیربهینه‌ای تولید کنند. اما در حالت کلی و برای کدهای استاندارد، افت سرعت چشمگیری ندارد و مزایای آن بر این ضعف غلبه می‌کند.

مفهوم اجرای به تعویق افتاده (Deferred Execution): این مکانیزم به این معناست که تعریف یک کوئری LINQ بلافاصله در خط نوشته‌شده اجرا نمی‌شود؛ بلکه اجرای واقعی آن تا زمانی که واقعاً به داده‌ها نیاز پیدا کنید (مثلاً با صدا زدن متدهایی مثل .ToList()، .Count() یا استفاده از حلقه foreach) به تعویق می‌افتد.

سوالات متداول درباره LINQ در C# :

LINQ چیست؟

LINQ یا Language Integrated Query یک قابلیت در زبان C# است که به برنامه‌نویسان اجازه می‌دهد روی داده‌ها Query بنویسند. با استفاده از LINQ می‌توان داده‌ها را از Collectionهایی مانند List و Array یا منابعی مانند Database فیلتر، مرتب، گروه‌بندی و پردازش کرد

آیا LINQ جایگزین SQL است؟
خیر. LINQ جایگزین SQL نیست، بلکه یک روش برای نوشتن Query داخل محیط C# است.

برای مثال در Entity Framework Core، شما با LINQ Query می‌نویسید و EF Core آن را به SQL تبدیل کرده و برای Database ارسال می‌کند.

آیا LINQ روی List کار می‌کند؟
بله. یکی از رایج‌ترین استفاده‌های LINQ کار روی Collectionهای داخل حافظه است.

تفاوت LINQ و Lambda چیست؟

این دو جایگزین هم نیستند.

Lambda Expression یک روش کوتاه برای نوشتن تابع است:

x => x.Age > 18

اما LINQ یک تکنولوژی برای Query کردن داده‌ها است.

LINQ معمولاً از Lambda Expression استفاده می‌کند.

مثلاً:

users.Where(x => x.Age > 18);

اینجا:

  • Where مربوط به LINQ است.
  • x => x.Age > 18 یک Lambda Expression است.

اگه خواستی ویدیو کامل همه این ها رو داخل کانال فارسی یوتیوب ما هست به این آدرس :https://www.youtube.com/@BackendWithCsharpFA

دیدگاه‌ خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

پیمایش به بالا