دسترسی به منابع دادهای با LINQ
لینک
LINQ، سرنام Language-Integrated Query، از جمله راهکارهای مؤثر در دسترسی
به دادهها است. امروزه، رقابت اصلی میان تولیدکنندگان ابزارهای
برنامهنویسی بر سر دسترسی سریع و آسان به منابع دادهای است. لینک چارچوب
مستحکمی را به وجود میآورد که دسترسی به اطلاعات ذخیرهشده روی طیف
گستردهای از منابع دادهای را امکانپذیر میکند و همانند پلی برای
برقراری ارتباط میان اشیا برنامهنویسی و دادهها استفاده میشود.
پیش
از ظهور لینک، محاورهها با رشتههای سادهای که در یک برنامه کاربردی
ساخته میشدند و حتی فاقد ویژگی IntelliSense بودند، استفاده میشدند. اما
با ظهور لینک، این شکل دسترسی به دادهها کاملاً متحول شد و برنامهنویسان
توانستند با حداقل کدنویسی محاورهها را از یک رشته ساده خارج کرده و به
محاورههایی تبدیل کنند که مدیریت بیشتر روی آنها امکانپذیر باشد. منعطف
بودن لینک باعث محبوبیت آن شد. کدنویسان بدون اینکه درگیر قواعد بسیار
پیچیده دسترسی به منابع دادهای مختلف شوند، موفق شدند بهراحتی برای
دسترسی به دادههایی که روی منابع مختلفی همچون بانکهای اطلاعاتی
رابطهای، اسناد xml و... قرار دارند، از لینک استفاده کنند. با این مقدمه،
به سراغ معرفی تعدادی از تکنیکهای پرکاربرد در لینک خواهیم رفت که برای
دسترسی به دادههایی که روی منابع مختلف قرار دارند، استفاده میشود. اما
ابتدا باید با ساختمان درونی محاورهها در لینک آشنا شویم.
محاوره چیست؟
پرسوجو
(Query) که به نام محاوره نیز شناخته میشود، رشتهای متنی است که
بهمنظور بازیابی دادهها از یک منبع دادهای، بهروزرسانی، اضافه کردن و
حذف دادهها، از آن استفاده میشود. لینک با هدف ارائه یک مدل ساده از
محاورهها در اختیار برنامهنویسان قرار گرفت؛ مدلی که قادر است به منابع
دادهای مختلف به شیوه کدنویسی یا ویزاردی متصل شود. برای این منظور
مجموعهای از متدهای اصلی که عملگرهای استاندارد محاوره (SQO) نام دارند،
لینک را یاری میکنند. طیف گستردهای از این متدها به شکل ترتیبی کار
میکنند؛ به این معنی که شی مورد محاوره از نوع یکی از رابطهای
<IEnumerable<T یا <IQueryable<T خواهد بود. شایان ذکر است
IQueryable که برای محاورههای LINQ TO SQL استفاده میشود، در نهایت به
IEnumerable تبدیل میشود. در نتیجه یک محاوره لینک همواره با اشیا سروکار
دارد.
مطلب پیشنهادی
Bloks زیرساختی آموزش محور
نکته
بارز و شاخص این مدل به ویژگی یکدست بودن آن بازمیگردد؛ به طوری که
برنامهنویسان در اکثر مواقع از الگوی ثابتی بهمنظور بازیابی دادهها از
منابع دادهای استفاده میکنند. محاورههای ساختهشده توسط لینک، عبارات
باقاعدهای هستند که همراه با فیلترهای مختلفی همچون مرتبسازی، تجمع و...
قابل بهرهبرداری هستند. استخراج ساختمند دادهها در عمل به طراحان و
بهویژه طراحان وب کمک فراوانی میکند. روشهای SQO روشهای توسعهیافتهای
هستند که از کلاسهای Enumerable و Queryable تعریف میشوند. بعضی منابع
این روشها را عملگرهای پرسوجو نامگذاری کردهاند. همگی این روشها در
فضایی به نام System.Linq قرار دارند. بهطور کلی محاورهها در لینک، در
پنج گروهی که در جدول شماره یک مشاهده میکنید، قرار میگیرند.
جدول شماره 1: پنج گروهی که نقش تدارکبینندهها را برای لینک بازی میکنند.
در کنار این پنج گروه اصلی، کتابخانههای جانبی دیگری نیز وجود دارند که برای مقاصد خاص استفاده میشوند.
LINQ
to Active Directory از جمله این موارد است. در میان گروههای جدول شماره
یک، دو گروه LINQ to Objects و LINQ to SQL پرکاربردترین گروههایی هستند
که برنامهنویسان استفاده میکنند. در بسیاری از موارد، برنامهنویسان
ترجیح میدهند به جای استفاده از محاورههای SQL، از محاورههایی که LINQ
to SQL در اختیار آنها قرار میدهد، استفاده کنند. به دلیل اینکه در عمل،
مکانیزم سادهتری را برای دسترسی به دادهها در اختیار آنها قرار میدهد.
در کنار این تدارکبینندهها، عملگرهای محاورهای دیگری نیز وجود دارد که
در یک عبارت محاوره از آنها استفاده میشود. پرکاربردترین این عملگرها در
جدول شماره دو آمده است.
جدول شماره 2: پرکاربردترین عملگرهایی که در محاورههای لینک استفاده میشوند.
ساختار و نحوه اجرای محاورهها در لینک
اجرای
محاورهها در لینک مکانیزم خاص خود را دارد. اولین مرحله، اتصال به منبعی
است که دادهها درون آن قرار دارند. مرحله دوم، تعریف رشته محاورهای است.
این رشته تعیینکننده منبع دادهای و دادههایی است که از آن منبع دریافت
خواهید کرد. سومین مرحله اجرای محاوره است. اجرای یک محاوره با استفاده از
حلقه foreach انجام میشود. در این حالت دادههای دریافتشده از منبع درون
یک متغیر رشتهای قرار میگیرند. زمانیکه همه عناصر پردازش شدند، رشته
قابل استفاده خواهد بود.
فهرست شماره یک، مثال سادهای از نحوه دسترسی
به یک منبع دادهای، ساخت رشته بازیابی و دریافت دادهها از این منبع را
نشان میدهد. این محاوره زمانی قابل استفاده خواهد بود که در حلقه foreach
استفاده شود. در این حالت متغیر مربوط به محاوره اجرا میشود و به سراغ
منبع دادهای خواهد رفت که برای آن تعیین شده است و در ادامه، دادهها را
بر مبنای الگویی که در محاوره مشخص شده است، دریافت خواهد کرد.
static void Main(string[] args)
{
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
var myQuery =
from num in numbers
where (num % 2) == 0
select num;
foreach (int num in myQuery)
{
Console.Write(“{0,1} “, num);
}
}
فهرست شماره یک
شکل
1 ساختار کلی یک محاوره و نحوه اتصال آن به یک منبع دادهای را همراه با
اجزا درون محاوره نشان میدهد. نکتهای که در خصوص لینک باید به آن توجه
کنید، این است که در لینک، اجرای یک محاوره متفاوت با خود محاوره است. به
عبارت دیگر، با ساخت یک رشته محاورهای، هیچ دادهای در اختیار شما قرار
نخواهد گرفت تا محاوره ساختهشده را اجرا کنید.
شکل 1: نحوه اجرای یک محاوره در لینک
منبع دادهای چیست؟
در
فهرست شماره یک، منبع دادهای یک آرایه بود که بهطور صریح از رابط
<IEnumerable<T پشتیبانی میکرد. این بدان معنا است که محاورههای
لینک روی اشیایی که از رابط IEnumerable ارثبری داشته باشند، بهراحتی
پیادهسازی میشوند. حلقه foreach برای اجرای محاورهها به IEnumebrale یا
<IEnumerable<T نیاز دارد. نوعهایی که از رابط <IEnumerable<T
یا رابطهایی همچون <IQueryable<T مشتق میشوند، نوعهای قابل
پرسوجو هستند. لینک میتواند از یک نوع قابل پرسوجو به شکل یک منبع داده
مستقیم، استفاده کند. اما یک منبع داده، همیشه یک آرایه ساده نیست. اگر
منبع مورد تقاضا یک بانک اطلاعاتی از نوع SQL Server باشد، تدارکبیننده
LINQ to SQL استفاده خواهد شد. در حالی که اگر منبع داده شما بانک اطلاعاتی
دیگری باشد، باید از LINQ to Dataset استفاده کنید. اگر منبع دادهای
درخواستی شما یک فایل XML باشد، تدارکبیننده LINQ to XML برای ساخت و
اجرای محاورهها استفاده میشود.
هدف از ارائه لینک کار با دادهها به
شیوه ساده و مستقیم است. لینک یک لایه برنامهنویسی انتزاعی میان زبانهای
تحت داتنت و منابع دادهای فراهم میآورد. شاید این سؤال پیش آید که چه
لزومی دارد برای دسترسی به منابع دادهای از محاورهها استفاده کنیم؟ در
پاسخ باید گفت که هر کدام از رابطهایی که برای دسترسی به دادهها از آنها
استفاده میشود، ترکیب نحوی خاص خود یا زبانی را که از آن استفاده
میکنید، در اختیار دارند؛ در نتیجه همواره باید با قواعد و ترکیبات نحوی
هر منبع دادهای و زبان برنامهنویسی هدف آشنایی داشته باشید. در مقابل
لینک این قابلیت را در اختیار شما قرار میدهد تا از چارچوب استانداردی
برای دسترسی به دادههای قرارگرفته در منابع دادهای مختلف استفاده کنید.
محاوره شماره یک؛ دسترسی به منابع دادهای ساده همچون آرایهها
آرایهها
سادهترین منبع دادهای هستند که میتوانید دادههای مدنظر را از آنها
استخراج کنید. در حالی که عناصر درون آرایهها را میتوان با استفاده از
حلقههایی همچون foreach یا for استخراج کرد، لینک نیز میتواند همین کار
را به شکل ساختیافتهای انجام دهد. فهرست شماره دو نحوه پیادهسازی یک
محاوره لینک روی یک آرایه را نشان میدهد.
static void Main(string[] args) { String[] myArray = { “One”, “Two”, “Three”, “Four”, “Five” };
var MyQuery =
from mystring
in myArray
select mystring;
foreach(var str in MyQuery)
Console.WriteLine(str); }
فهرست شماره دو
محاوره شماره دو؛ محدود کردن دادههای دریافتی از یک منبع داده
محاوره
شماره یک، همه دادههای درون یک آرایه را بازمیگرداند؛ اما اگر در نظر
داشته باشیم تنها دادههای خاص خود را استخراج کنیم، باید از کلمه کلیدی
where استفاده کنیم. این کلمه کلیدی به شما اجازه میدهد تا شرطی را روی یک
محاوره پیادهسازی کنید. در اغلب موارد، محاورهها به فیلتر نیاز دارند؛
به دلیل اینکه در بیشتر زمانها نیازی نداریم کل مجموعه دادهها را از درون
یک منبع دادهای استخراج کنیم؛ بهویژه زمانی که منبع داده هدف ما یک بانک
اطلاعاتی مشتمل بر دهها هزار رکورد باشد. مکان قرارگیری کلمه where در یک
محاوره، بعد از کلمه from و قبل از کلمه کلیدی select است. در فهرست شماره
سه از ترکیب نحوی where بهمنظور محدودکردن خروجی دادههایی که اندازه
آنها از سه کاراکتر بیشتر است، استفاده کردهایم.
static void Main(string[] args)
{
String[] myArray = { “One”, “Two”, “Three”, “Four”, “Five” };
var MyQuery =
from mystring
in myArray
where mystring.Length > 3
select mystring;
foreach(var str in MyQuery)
Console.WriteLine(str);
}
فهرست شماره سه
محاوره شماره سه؛ مرتبسازی و گروهبندی دادههای بازیافتشده در یک محاوره
برای
چینش دادههای بازیافتی در یک محاوره از کلمه کلیدی orderby استفاده
میشود. با استفاده از این کلمه کلیدی نحوه مرتبسازی دادهها، مطابق با
نیاز کاری شما خواهند بود. در کنار عملگر orderby روشها و عملگرهای دیگری
نیز برای مرتبسازی دادهها در اختیار شما قرار دارند. فهرست شماره چهار
نحوه مرتبسازی دادهها با عملگر orderby را نشان میدهد.
class Program
{
public class myclass
{
public string Name { get; set; }
public int Age { get; set; }
}
static void Main(string[] args)
{
myclass[] mystrings = { new myclass { Name=”Barley”, Age=8 },
new myclass { Name=”Boots”, Age=4 },
new myclass { Name=”Whiskers”, Age=1 } };
IEnumerable<myclass> query = mystrings.OrderBy(Program => Program.Age);
foreach (myclass mystr in query)
{
Console.WriteLine(“{0} - {1}”, mystr.Name, mystr.Age);
}
}
}
فهرست شماره چهار
محاوره شماره چهار؛ متصل کردن نتایج بهدستآمده از محاورهها
در
برخی موارد، محاورهها تنها روی یک منبع دادهای خاص اجرا نمیشوند و ما
به دادههایی نیاز داریم که درون منابع دادهای مختلف وجود دارند. در چنین
شرایطی لازم است تا محاورهها را به شکلی به یکدیگر متصل کنیم. فهرست شماره
پنج نحوه به کارگیری این تکنیک را نشان میدهد.
static void Main(string[] args)
{
Int32[] FirstArray= {1,2,3,4,5};
Int32[] SecondArray = { 6,7,8,5,4};
var MyQuery = from QueryA in FirstArray
from QueryB in SecondArray
where QueryA == QueryB
select new { QueryA, QueryB };
foreach(var str in MyQuery)
Console.WriteLine(str);
}
فهرست شماره پنج
محاروه شماره پنج؛ نحوه پیادهسازی یک شرط روی یک محاوره
بعضی
مواقع با محاورههایی برخورد میکنید که مجبور میشوید عملیاتی را روی چند
عنصر انجام دهید تا اطلاعات مورد نیازتان را دریافت کنید. اگر این عملیات
تکراری را به دفعات با محاورهها انجام دهید، وقت زیادی از شما گرفته
میشود. لینک به شما پیشنهاد میکند از Let برای ساخت مقادیر جدیدی که در
ادامه به کار میروند، استفاده کنید. فهرست شماره پنج نحوه به کارگیری کلمه
کلیدی Let را همراه با ترکیب دو محاوره با یکدیگر نشان میدهد. (شکل 2)
شکل 2: نحوه پیادهسازی یک شرط روی محاوره
static void Main(string[] args)
{
Int32[] ArrayA = {1,2,3,4};
Int32[] ArrayB = { 1,2,3,4};
var MyQuery =
from QueryA in ArrayA
from QueryB in ArrayB
let TheSquare = QueryA * QueryB
where TheSquare > 4
select new { QueryA, QueryB, TheSquare };
foreach(var str in MyQuery)
Console.WriteLine(str); }
فهرست شماره پنج
در شماره آینده به بررسی تکنیکهای دیگر مربوط به لینک خواهیم پرداخت.