Linq: تحولی بزرگ در کار با داده ها، جایگاه آن در دات نت
فناوری مایکروسافت برای کار با منابع داده مختلف با استفاده از یک زبان مشترک
زبانهای برنامه نویسی امروزی اکثراً شیء گرا[1] هستند ولی پایگاههای دادهها[2] همانطور رابطهای[3] باقی ماندهاند که علت این مسئله یکی کارایی بالای سیستمهای رابطهای، و دیگری وجود اکثر پایگاه های داده های موجود به این شیوه است که هزینهی تبدیل آنها به سیستمهای شیء گرا بسیار بالاست؛ به همین خاطر و البته دلایل دیگر پایگاه دادههای شیءگرا[4] (مثل O2) از توجه کمی برخوردار شدند. به همین سبب تلاشها معطوف شد به تولید واسطی[5] میان زبانهای برنامه نویسی شئیءگرا و پایگاه داده ها به نام شیء-رابطه نگارندهها[6] یا ORMها.
این واسط دیدگاهی کاملاً شیئگرا نسبت به جداول و اصولاً اشیاء موجود در DB دارد ( از جمله dbهای xmlای یا semi structured). با استفاده از این فنآوری، واسطهای برنامهنویسی کاربردی ارائه میشود که به راحتی توانایی ذخیره سازی اشیاء در داخل پایگاه داده را برای برنامه نویس فراهم میکند و همچنین توانایی انجام پرس و جوها[7] نیز با دیدگاهی کاملاً شئ گرا انجام میشود. به علاوه این واسط با کمک دیگر اجزاء نرمافزاری توانایی انجام عملیات بر روی پایگاه داده در قالب تراکنش ها را ایجاد میکند. این فنآوریها همگی با پایگاه دادههای رابطهای کار میکنند و در پشت همهی آنها راهبر[8] مخصوص به هر پایگاه داده خاص قرار میگیرد (مثلا برای Oracle یا Microsoft SQL Server یا MySql و غیره).
این فنآوری را میکروسافت در شیء یا ابزار LINQ to SQL پیادهسازی کرده است؛ با این ابزار میتوان با کد برنامه نویسی محتوای پایگاه داده را تغییر داد و با استفاده از SqlMetal[9] تمام جداول پایگاه داده را به صورت کلاسهای موجودیت تبدیل کرد[10].
مایکروسافت در محیط برنامه نویسی ویژوال استودیو 2008 از جدید ترین فنآوری خود یعنی dot net Framework 3.5 استفاده کرده است؛ اگر یک وب سایت را با این ابزار برنامه نویسی کنید عملا آسودگی خاطر و سرعت عمل را مشاهده خواهید کرد. از مهمترین ویژگیهای این نسخه میتوان به قابلیت تولید نرم افزارهای تحت ویستا نیز اشاره کرد. گفته میشود 250 ویژگی جدید و منحصر به فرد در این نسخه وجود دارد.
یکی از ویژگیهای جالب توجه، LINQ میباشد، LINQ در واقع زبان پرس و جوی یکپارچه با زبان (برنامهنویسی) (Language Integrated Query) است. با استفاده از این ویژگی، برنامه نویس فقط کافی است بگوید از پایگاه داده چه میخواهد، دیگر لازم نیست سطرهای زیادی کدنویسی را انجام دهد؛ مایکروسافت تصمیم گرفته است این فنآوری را نهادینه کند[11].
مقدمه
دات نت به عنوان یکی از فريمورکهای پياده سازی نرم افزار در سالیان اخير، امکانات متعددی را جهت کار با داده در اختيار پياده کنندگان نرم افزار قرار میدهد. LINQ تلاشی است جهت يکپارچگی عميقتر و بیشتر بین زبانهای برنامه نویسی و داده. در واقع LINQ مشتمل بر مجموعهای از عملگرهای پرس و جوی استاندارد است که معماری لازم جهت حرکت، فيلترينگ و اجرای عملیات بر روی تقريبا" هر نوع منبع داده نظیر XML، بانکهای اطلاعاتی رابطهای و اشياء درون حافظه را فراهم مینماید[12].
LINQ که سرنام Language Integrated Query است، یکی از متدولوژیها و مدلهای برنامه نویسی میکروسافت است که عملاً قابلیتهایی را در خصوص امکان "پرس و جو"، به زبانهای مبتنی بر NET. اضافه میکند. LINQ ساختار گرامری فشرده، گویا و هوشمندی برای پردازش و مدیریت دادهها دارد. ارزش واقعی آن از فراهم ساختن امکان اجرای یک پرس و جو در یک بانک اطلاعاتی SQL، یک DataSet، آرایهای از اشیاء در حافظه، و بسیاری از انواع دادههای دیگر ناشی میشود.
LINQ از ساختار گرامری SQL گونهای برای آماده سازی پرس و جوها استفاده میکند که بسیار فراتر از SQL مستتر در زبانهای برنامه نویسی است. دلیل این امر آن است که SQL مستتر در زبانهای برنامه نویسی از ساختار گرامری ساده شده و سرراستی برای افزودن امکان پرس و جو به آن زبانها استفاده میکند. از این رو، امکان به کارگیری قابلیتهایی چون توابع داخلی SQL در پرس وجوهای SQL مستتر در زبانهای برنامه نویسی وجود ندارد؛ اما این قابلیت در LINQ فراهم شده است، چرا که پیاده سازی آن به گونهای است که میتوان ساختارهای گرامری، توابع و انواع راهکارها یا مکانیزمهای "تبدیل نوع دادهها" را بکار برد. همچنین، از LINQ میتوان برای دستیابی به انواع دادهها استفاده نمود، اما SQL مستتر در زبانها صرفاً به پرس و جو از بانکهای اطلاعاتی محدود میشود که قابلیت مدیریت پرس وجوهای SQL را دارند[13].
تعریف
LINQ یک API است به منظور متمرکز کردن و ایجاد رفتار یکسانی برای کار با داده (با نوعهای گوناگون). به طوری که برنامه نویس برای دادههای با توع مختلف Array و XML و دیتابیس و .. به طور یکسان کد بنویسد. Linq یا Language Integrated Query نوع خاصی از زبان برنامه نویسی است برای انجام عملیات پرس و جو در هر Object ای. این شیء میتواند یک بانک یا پایگاه داده باشد، یک آرایه باشد، یک List Of باشد، یک فایل Xml باشد، یک DataSet باشد و ... linq روی هر دیتای قابل شمارشی میتواند کار کند.
از این جهت به آن نوعی از زبان گفته میشود که در واقع مجموعهای از syntax هاست که از قوانین خاص و ثابتی پیروی میکنند و تغییر زبان برنامه نویسی در آن اثری ندارد؛ فقط کافی است به یک زبان برنامه نویسی مادر اضافه شود. به همین دلیل است که نحوه کار Linq در #C و Vb.net فرقی با هم ندارد و تنها تفاوت آن در syntax دو زبان است. در کل مایکروسافت با ارایه این تکنیک پا را از یک DataAccess صرف فراتر گذاشته و نگاه کلیتری به امر پرس و جو داشته.
LINQ چيست؟
با این که فنآوری LINQ در پائيز سال 2005 مطرح گردید ولی فرآیند پیاده سازی آن از سال 2003 آغاز شده بود. هدف از ابداع فناوری فوق، ارائه تسهيلات لازم برای پياده کنندگان جهت کار با داده در بانکهای اطلاعاتی SQL و XML عنوان شده است. در واقع، وجود یک حلقه گمشده بین داده رابطهای (بانکهای اطلاعاتی)، اسناد XML با زبانهای برنامه نویسی، ضرورت ابداع فناوری فوق را توجيه کرده بود. پياده کنندگان مجبور بودند برای کار با هر يک از منابع داده، از روشهای متفاوتی استفاده نمایند. LINQ را میتوان به منزله حلقهای گمشده بین دنیای داده و زبانهای برنامه نویسی همه منظوره تصور کرد. با استفاده از LINQ امکان دستیابی به داده صرف نظر از نوع داده با روشی مشابه و یکسان فراهم میگردد.
پیاده کنندگان نرم افزار در زمان نوشتن برنامههای خود معمولا" از دو زبان مختلف جهت رسیدن به یک هدف مشترک استفاده مینمایند. ما برای نوشتن کدها از یک زبان برنامه نویسی نظیر VB.NET و يا #C و برای گفتگو با سیستم بانک اطلاعاتی از یک زبان دیگر نظیر SQL استفاده میکنيم.
برای سفارش شام خود از یک زبان و برای سفارش چای از زبان دیگر!
این موضوع میتواند چالشهای متعددی را برای پياده کنندگان نرم افزار به دنبال داشته باشد:
- در مواردی که فريمورک دات نت را به عنوان پلت فرم انتخاب کرده باشیم، دات نت قادر به درک کدهای SQL نخواهد بود.
- در مواردی که از زبانهای برنامه نویسی حمايت شده در دات نت جهت نوشتن کد در محيط ويژوال استوديو استفاده میکنيم، همواره یک ابزار قدرتمند در کنار ما است تا در صورت اشتباه در گرامر دستورات، توصیههای لازم را ارائه نماید ( IntelliSense). از ويژگی فوق نمیتوان در ارتباط با SQL استفاده کرد.
- امکان بررسی نوعها در زمان ترجمه وجود ندارد. این بدان معنی است که پياده کنندگان تا زمانی که برنامه اجراء نگردد، نمیتوانند مشکلات احتمالی را مشاهده و قبل از زمان اجراء با آنها برخورد نمایند.
- شرکت مايکروسافت امکانات متعددی را در فريمورک دات نت جهت کار با اسناد XML ارائه کرده است. ارائه System.Xml ،System.Xml.XPath و System.Xml.Schema نمونه هائی در این زمینه میباشند. پياده کنندگان نرم افزار در زمان کار با اسناد XML مجبور بودند که از فناوریهای متعددی نظیر DOM ( برگرفته شده از Document Object Mode ) و XQuery استفاده نمایند. همين موضوع باعث شده بود که کار با اسناد XML نظیر خواندن و یا نوشتن داده در آنها برای بسیاری از پياده کنندگان مشکل باشد.
شرکت مايکروسافت برای حل مشکلات فوق، بررسی دو راهکار را در دستور کار خود قرار داد:
- ایجاد پتانسیلهای مورد نیاز مختص XML و یا داده رابطهای در هر یک از زبانهای برنامه نویسی و زمان اجراء. راهکار فوق نه تنها مشکل اصلی را حل نمیکرد بلکه در مواردی مشکلات را خصوصا" در زمینه نگهداری افزایش میداد.
- اضافه کردن قابلیتهای همه منظورهی نوشتن query در فریمورک دات نت. به عبارت دیگر یک فریمورک همه منظوره با قابلیت نوشتن query درون فريمورک دات نت که زبانهای VB.NET و #C بتوانند به سادگی از مزایای آن استفاده نمایند.
- خوشبختانه، شرکت مایکروسافت گزينه دوم را انتخاب نمود. ایجاد یک زیرساخت جهت نوشتن query در بين اشياء، اسناد XML، داده رابطهای و ...
هم اینک پیاده کنندگان میتوانند از مزايای یک الگوی تعريفی در هر یک از زبانهای دات نت جهت کار با داده استفاده نمایند. ارائهی مجموعه اپراتورهای استاندارد جهت نوشتن query یکی از دستاوردهای مهم LINQ محسوب میگردد. بدین ترتیب، پياده کنندگان میتوانند با به کار گیری یک مجموعه يکسان از اپراتورهای نوشتن query در هر یک از زبانهای برنامه نویسی حمایت شده در دات نت، از داده ذخیره شده در منابع داده مختلف صرف نظر از نوع منبع داده استفاده نمایند. همچنين، امکان استفاده از پتانسیلهایی نظیر IntelliSense و بررسی نوعها در زمان ترجمه نیز وجود خواهد داشت.
شکل 1 نحوه عملکرد LINQ را نشان میدهد.

شکل 1 : عملکرد فناوری LINQ
مثال یک
در واقع هسته تفکر و اعمال linq با دو واسط قدیمی دات نت IEnumerable و IEnumerator پیریزی شده و هر دادهای که این واسطها را پشتیبانی کند در حلقههای ForEach و linq قابل استفاده است.
برای درک بهتر کاربرد لینکیو، به عنوان نمونه چند دستور ساده را مثال میزنیم: با فرض داشتن آرایه زیر
Dim arr() As Integer = {2, 5, 8, 9, 10, 8, 1, 7, 5, 8 , 3, 2, 25, 18}
این دستورات برقرار هستند:
- یک لیست شمارشی با حذف عناصر تکراری
From i In arr Distinct
- یک لیست شمارشی مرتب شده صعودی
From i In arr Order By i Ascending
- یک لیست شمارشی مرتب شده نزولی
From i In arr Order By i Descending
- یک لیست شمارشی مرتب شده با حذف تکرارها
From i In arr Distinct Order By i
- میانگین اعداد آرایه فوق
Aggregate i In arr Into Average(i)
- بیشینهی اعداد آرایه فوق
Aggregate i In arr Into Max(i)
- کمینه، بیشینه، میانگین و تعداد اعداد آرایه فوق
Aggregate i In arr Into Min(i), Max(i), Average(i), Count()
- کمینه، بیشینه، میانگین و تعداد اعداد آرایه فوق با نام جدید
Aggregate i In arr Into X = Min(i), Ali = Max(i), Reza = Average(i), Z = Count()
البته کار با این دستورات ساده تمام نمیشود و group و join و Where و... میتوان روی ساختارهای تو در توی شمارشی اعمال کرد و خروجی شمارشی یک بلوک linq را خوراک ورودی یک دستور دیگر کرد. اگر با زبان sql آشنایی داشته باشید در درک linq و محل کاربرد آن مشکلی نخواهید داشت.
مثال دو
برای آشنایی اولیه با قابلیت های LINQ، بدون این که بخواهیم وارد جزئيات شویم یک مثال کاربردی را با یکدیگر بررسی میکنیم. در اين مثال با استفاده از LINQ و با يک روش مشابه به منابع داده مختلفی متصل شده و پس از بازیابی داده، آنها را در يک ListBox جداگانه نمایش میدهيم. منابع داده عبارتند از:
- فولدرهای موجود در یک درایو
- پردازههای در حال اجراء در ويندور
- يک بانک اطلاعاتی رابطهای SQL
- عناصر موجود در يک آرایه
- يک فایل XML
- یک فایل متن
<%@ Page Language="VB" uiCulture="fa-IR" Culture="fa-IR" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import NameSpace="System.IO" %>
<%@ Import NameSpace="System.Linq" %>
<%@ Import NameSpace="System.Data.Linq" %>
<%@ Import NameSpace="System.Data.Linq.Mapping" %>
<%@ Import NameSpace="System.XML.Linq" %>
<%@ Import NameSpace="System.Collections" %>
<script runat="server">
'====================================================================
کلاس ایجاد شده بر اساس داده موجود در بانک اطلاعاتی Contact برای جدول Persons
LINQ to SQL Class
|
<Table(Name:="Persons")> _
Public Class Person
<Column(DbType:="Int not null")> _
Public ID As Integer
<Column(DbType:="nvarchar(50) not null")> _
Public Name As String
<Column(DbType:="nvarchar(50) not null")> _
Public Email As String
End Class
'====================================================================
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
بازیابی فولدرهای موجود در درایو C
|
Dim DI As DirectoryInfo = New DirectoryInfo("C:\\")
Dim dirQuery = From dir In DI.GetDirectories() Order By
(dir.Name) Select dir.Name
For Each item In dirQuery
ListBox1.Items.Add(item)
Next item
'====================================================================
بازیابی پردازه های در حال اجرا در ویندور
|
Dim procQuery = From proc In Process.GetProcesses() Order By proc.Id _
Descending Select proc.Id, proc.ProcessName
For Each item In procQuery
ListBox2.Items.Add(item.Id & " " & item.ProcessName)
Next item
'=====================================================================
بازیابی داده موجود در جدول Persons بانک اطلاعاتی Conatct
|
Dim context As DataContext = New DataContext("Data Source=SRCO-1\SQLEXPRESS;
Initial Catalog=Contact;Integrated Security=true")
Dim contact1 As Table(Of Person) = context.GetTable(Of Person)()
Dim query = From c In contact1 Select c.Name, c.Email
For Each item In query
ListBox3.Items.Add(item.Name & " " & " ==== ◄ " & item.Email)
Next item
'=======================================================================
Dim firstnames As String() = {"سخا روش", "سايت شرکت سخا روش", "سايت مقالات به زبان فارسی", "سری مقالات ", "ایران", "تهران"}
Dim val As IEnumerable(Of String) = From fn In firstnames _
Where (fn.StartsWith("س")) _
Select fn
For Each name As String In val
ListBox4.Items.Add(name)
Next name
'========================================================================
بازیابی داده ذخیره شده در یک فایل XML با نام Cities.xml
|
Dim XDoc As XDocument = XDocument.Load(MapPath("Cities.xml"))
Dim query1 = From c In XDoc.Descendants("City") _
Order By c.Element("Name").Value _
Select c.Element("Name").Value
For Each item In query1
ListBox5.Items.Add(item)
Next item
'======================================================================
بازیابی داده از یک فایل متن با نام Maghalat.csv
|
Dim query2 = From line In File.ReadAllLines(MapPath("Maghalat.csv")) _
Where Not line.StartsWith("#") _
Let parts = line.Split(",") _
Select Title = parts(0), Publisher = parts(1)
For Each item In query2
ListBox6.Items.Add(item.Title & " " & item.Publisher)
Next item
End Sub
</script>
'=======================================================================
|
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title> مثال شماره یک </title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" runat="server"></asp:ListBox>
<asp:ListBox ID="ListBox2" runat="server"></asp:ListBox>
<asp:ListBox ID="ListBox3" runat="server"></asp:ListBox>
<asp:ListBox ID="ListBox4" runat="server"></asp:ListBox>
<asp:ListBox ID="ListBox5" runat="server"></asp:ListBox>
<asp:ListBox ID="ListBox6" runat="server"></asp:ListBox>
</div>
</form>
</body>
</html>
|
شکل زیر خروجی برنامه بالا را نشان میدهد:

شکل 2: دستیابی به منابع داده مختلف با استفاده از فنآوری LINQ
خلاصه
LINQ يک فناوری قدرتمند در زمان کار با داده است که دستاوردهای متعددی را برای پياده کنندگان به ارمغان آورده است:
- روشی ساده جهت نوشتن query
- تسریع در پیاده سازی نرم افزار با توجه به حذف خطاهای زمان اجراء
- امکان استفاده از امکاناتی نظیر اشکال زدائی و IntelliSence در زمان پياده سازی
- حذف خلاء موجود بين داده رابطهای و پیاده سازی شیءگراء
- استفاده از یک گرامر يکسان جهت نوشتن query صرف نظر از نوع منبع داده
- افزایش بازدهی و راندمان برنامه نویسی، چرا که برنامه نویسان از یک رویکرد يکسان برای نوشتن query و بهنگام سازی داده از طریق زبان برنامه نویسی استفاده خواهند کرد.
LINQ از دو بخش که مکمل يکديگر میباشند تشکيل شده است:
- مجموعهای از ابزارها جهت کار با اشياء، اسناد XML، بانکهای اطلاعاتی رابطهای و سایر نوعهای داده، و
- مجموعهای از ضمایم برای زبانهای برنامه نویسی نظیر VB و #C.
منابع