انجمن گروه موج سازان
مروری بر LINQ در C# 2008 - نسخه قابل چاپ

+- انجمن گروه موج سازان (http://www.mojsazan.com/forum)
+-- انجمن: برنامه نویسی تخصصی (http://www.mojsazan.com/forum/forumdisplay.php?fid=31)
+--- انجمن: DataBase (http://www.mojsazan.com/forum/forumdisplay.php?fid=35)
+---- انجمن: LINQ (http://www.mojsazan.com/forum/forumdisplay.php?fid=46)
+---- موضوع: مروری بر LINQ در C# 2008 (/showthread.php?tid=125)



مروری بر LINQ در C# 2008 - مهرداد عباسی - 12-16-2009

امروزه دیگر نمی­توان منکر کاربرد نرم­افزار­های کامپیوتری در زندگی روزمره بشر گردید. همچنین در اکثر برنامه­هایی که امروزه بر روی کامپیوتر­ها به کار می­روند، استفاده از بانک­های اطلاعاتی انکارناپذیر است. به همین دلیل از اوایل دهه 80 میلادی تلاش­های فراوانی برای بهبود نرم­افزاری­های بانک اطلاعاتی گردید و منجر به ظهور مدل­های جدید و متعددی برای ایجاد پایگاه­های داده گردید. یکی از این مدل­ها که هم اکنون در بسیاری از نرم­افزارها پیاده سازی شده است مدل RDBMS می­باشد. به عنوان نمونه می­توان SQL Server و همچنین Oracle را نام برد. در حال حاضر، برای ایجاد و توسعه برنامه­های مبتنی بر بانک­های اطلاعاتی، این دو نرم­افزار بیشتر از مدل­های مشابه مورد استفاده قرار می­گیرند.

پس از انتخاب نرم­افزار ارائه دهنده خدمات بانک اطلاعاتی، نوبت به انتخاب زبان برنامه نویسی می­رسد. در اینجا نیز ذکر این مورد کافیست که اگر نگاهی که گذشته داشته باشیم متوجه می­شویم که در بیست سال گذشته زبان­هایِ با قابلیت برنامه نویسی شئ­گرا به عنوان اولین و بهترین زبان برای توسعه نرم­افزارها در نظر گرفته می­شوند. در میان زبان­های با قابلیت برنامه نویسی شئ­گرا زبان #C و Java از امکانات بهتری برخوردارند.

با نگاهی به دو نرم­افزار انتخاب شده در بالا متوجه به تضادی می­شویم که از گذشته تا کنون گریبان­گیر برنامه­نویسان متعددی بوده است. با توجه به اینکه SQL Server یک بانک اطلاعاتی رابطه­ای است پس نمی­توان با آن به صورت شئ­گرا در برنامه­­ها ارتباط برقرار کرد. البته مایکروسافت برای رفع این مشکل تا قبل از سال 2005 فعالیت­هایی نظیر ارائه DataSet و ADO.NET انجام داده است. اما با این حال هنوز نمی­توان به صورت کاملاً شئ­گرا با این مدل از بانک­های اطلاعاتی ارتباط برقرار کرد.

در این میان شرکت­های مطرح نرم­افزاری دنیا مانند Mircrosoft نیز بیکار نمانده­اند و بر روی پروژه­هایی برای رفع مشکل یاد شده در بالا فعالیت نموده­اند. مهمترین و بهترین پروژه­ای که در این مورد بر روی آن کار شده است پروژه LINQ می­باشد. با استفاده از این تکنولوژی دیگر نیاز به کار بردن روش­های متفاوت برای بازیابی اطلاعات از منابع داده­ای گوناگون مانند بانک­های اطلاعاتی رابطه­ای، اسناد XML و حتی اشیاء درون حافظه نیست. در این روش از یک گرامر مشابه برای بازیابی اطلاعات از هر نوع منبع داده­ای استفاده می­شود؛ و البته گرامری که این روش از آن استفاده می­کند به صورت شئ­گرا می­باشد.

در ادامه نگاهی کلی بر فرم کلی این روش خواهیم انداخت و سپس به توضیح و بررسی قسمت­های مخلتف پروژه می­پردازیم.

برای درک کلی گرامر این روش مثال زیر را در نظر بگیرید:



کد پی‌اچ‌پی:
int[ ] i= {1,2,3,4,5,6,7,8,9,10,11};

var 
query from p in i

            where p
>=5      

            select p
;

objectdumper.write(query); 

اگر کدهای بالا را کامپایل و اجرا کنید کلیه اعدادی که در آرایه i از عدد 5 بیشتر می­باشند انتخاب و در متتغیر query ذخیره می­شوند. این مدل استفاده از LINQ به مدل عملگری مشهور است. کامپایلر #C پس از برخورد با این عبارت آن را به فراخوانی متد­هایی تبدیل می­کند. پس از تبدیل، عبارت پرس و جوی بالا به صورت زیر در خواهد آمد.

var query= i.where(p=> p>5);

خروجی هر دو مدل معادل یکدیگر می­باشند. متغیر p که در هر دو حالت از آن استفاده شده است برای حرکت در مجموعه مورد نظر، به کار می­رود و در هر بار به یک عنصر در این مجموعه اشاره می­کند.

در مورد کلاس ObjectDumper باید به عرض برسانم که این ابزار یک کلاس ساده با یک متد به نام ()Write است و از آن برای تهیه خروجی قالب­دار استفاده می­شود. این بدان معناست که دیگر برای چاپ اطلاعات لازم نیست با استفاده از ساختارهای تکرار در مجموعه مورد نظر حرکت کنید و با استفاده از متد ()Writeو یا ()WriteLine که در کلاس Console قرار دارند اطلاعات را چاپ کنید.

ObjectDumper هنگام نصب NET. بر روی کامپیوتر شما کپی می­شود. بنابراین برای استفاده از آن کافییست فایل Objectdumper.cs را جستجو کرده و آن را به پروژه خود اضافه کنید.

اما اگر به جای استفاده از LINQ، بخواهیم با استفاده از روش­های متداول قبلی این کار را انجام دهیم باید از دستوراتی مانند زیر استفاده نمود.


کد پی‌اچ‌پی:
int[] i= {1,2,3,4,5,6,7,8,9,10,11};

for (
int j 0i.Length j++)

{

    if (
i[j]>=5)

    {



همانطور که مشاهده می­کنید استفاده از LINQ برای بازیابی اطلاعات بسیار ساده­تر و قابل فهم­تر می­باشد. البته مزیت دیگر این تکنولوژی به گرامر آن بر­می­گردد. گرامر LINQ بسیار شبیه به گرامر SQL است؛ با توجه به اینکه کمتر برنامه­نویسی پیدا می­شود که با گرامر SQL آشنایی نداشته باشد، لذا استفاده از این گرامر بهترین انتخاب برای این تکنولوژی به حساب میرود.

در ادامه قصد دارم که با بررسی مثالی پیچیده­تر وارد جزئیات LINQ شوم. برای این منظور ابتدا یک کلاس به نام Person که دارای 4 خصوصیت می باشد به صورت زیر تعریف می­کنم.

کد پی‌اچ‌پی:
List<Personpeople = new List<Person>

{

   new 
Person{ID=1IDRole=1LastName="Andy"FirstName="Brad"},

   new 
Person{ID=2IDRole=2LastName="Gray"FirstName="Tom" },

   new 
Person{ID=3IDRole=2LastName="Gran"FirstName="Mary"},

   new 
Person{ID=4IDRole=3LastName="Cops"FirstName="Gary"}

};

var 
query from p in people

                 where p
.FirstName.Length  ==  4

                 select 
new

            {

                
p.FirstNamep.LastName

            
};

ObjectDumper.Write(query);
        
Console.WriteLine(i[j]);

    } 


در این برنامه چند نکته جالب توجه وجود دارد که از خصوصیت جدید C# 3.0 می باشد. در ابتدای کار ممکن است تعجب کنید که چرا برای شئ people نوعی در نظر گرفته نشده است و از کلمه کلیدی var استفاده شده است.

آیا var یک نوع جدید در C# می باشد؟ در جواب باید گفت که نه؛ در C# 3.0 می­توان متغیرهای محلی با نوع­های ضمنی ایجاد کرد. این بدان معناست که دیگر الزامی نیست که برای متغیرها حتماً یک نوع عرفی تعیین کنید و با گذاشتن کلمه کلیدی var قبل از تعریف متغیر به کامپایلر اعلام می­کنید که نوع این متغیر را براساس عبارتی که برای مقداردهی اولیه آن در نظر گرفته شده است تعیین کند.

به عنوان مثال هر دو دستور زیر معادل یکدیگر می باشند:

var n = 5;

int n = 5;

در استفاده از کلمه کلیدی var باید توجه داشته باشید که متغیری که با این نوع اعلام می­شود باید حتماً مقداردهی اولیه گردد؛ در غیر اینصورت برنامه با خطای کامپایلری روبرو می­شود.

استفاده از کلمه کلیدی var برای تعیین نوع خروجی پرس و جوهای پیچیده­ای که در ادامه ممکن است با آنها روبرو شویم بسیار مفید است و برنامه نویس را از قید تعیین یک نوع تعریف شده برای خروجی پرس و جوها آزاد می­سازد.

به توضیح ادامه برنامه بالا برمی­گردیم. در ابتدا یک شئ از نوع <List<T به نام people ایجاد شده است. در تعریف این شئ یکی دیگر از خصوصیات C# 3.0 مشاهده می­شود. این خصوصیت تحت عنوان مقداردهنده اولیه به اشیاء شناخته می شود.

با استفاده از مقداردهنده اولیه به اشیاء، همانند مقداردهنده اولیه به آرایه­ها، می­توانید بدون فراخوانی سازنده کلاسی که از روی آن نمونه­سازی انجام می­گیرد (و یا فراخوانی متدهایی که برای درج در نظر گرفته شده اند مانند ()Add در کلاس <List<T با استفاده از یک خط کد یک شئ از روی کلاس ایجاد و مقداردهی کرد. برای درک بیشتر به مثال زیر توجه کنید:
کد پی‌اچ‌پی:
Person p1= new Person{ID 1FirstName="A"LastName="A"};

Person p2 = new Person();

p2.ID 1

مشاهده می­کنید که با استفاده از این خصوصیت کار ایجاد اشیاء چقدر آسانتر می­شود. در ادامه با استفاده از یک پرس و جو ساده نام و نام خانوادگی افرادی که طول فیلد نام آنها برابر 4 باشد بازیابی و نشان داده می­شود.

همانطورکه مشاهده می­کنید دستوری که برای این منظور در نظر گرفته شده است بسیار شبیه به دستور قبلی است.

امیدوارم که تا اینجای کار متوجه اصول کلی کار با LINQ شده باشید. در LINQ عملگرهای پرس و جو بسیاری وجود دارد؛ اما به دلیل کمبود وقت از تشریح آنها صرف نظر می­کنم. البته در انتهای مطلب برای مطالعه بیشتر منابعی را که مورد استفاده قرار داده­ام ذکر خواهم کرد.

تا بدین جا نحوه استفاده از LINQ برای بازیابی اطلاعات از اشیاء درون حافظه مورد بررسی قرار گرفت.

منابع مورد استفاده :

· کتاب "LINQ در C# 2008" تالیف گروه واژه

· Ebook های موجود در سایت PersiaDevelopers