PDA

برای دیدن نسخه كامل اینجا را كلیك كنید : جستجو با استاندارد xlinq‌ قسمت 1



kolak2
2007/11/09, 07:13 PM
چكيده:

مقاله‌اي كه در پيش رو داريد به توضيح روش‌هاي پرس‌وجو با استفاده از XLinq مي‌پردازد. اين روش‌هاي مختلف در جدولي نشان داده شده است. عملگر‌هاي مختلفي براي اين منظور معرفي شده‌اند و عملكرد هر يك نيز جداگانه توضيح داده شده است.
كليد واژه:

عملگر‌هاي پرس‌وجوگر
Xml,xpath, query operators


</SPAN>
امروزه XLinq قدرت پرس‌وجویی بسیار فراتر از روش‌های متداول جهت بازگرداندن XMLو پرس‌وجوی آن به وسیلهXPath دارد.
در بخش اول این سری مقاله‌ها (http://www.sayan.ir/ViewArticle.aspx?ArticleID=145)، به قابلیت XLinq جهت ایجاد، تغییر و حذف داده‌های XML پی بردید. بر اساس این پیش‌زمینه، مقاله حاضر ابتدا به ویژگی‌های پرس‌وجوی XLinqپرداخته، عملگر‌های پرس‌وجوگر[1] (http://sayan.ir/ViewArticle.aspx?ArticleID=150#_ftn1) آماده شده توسط LINQ را بررسی كرده و سپس مثال‌هایی از كاربرد آنها در عملیات پرس‌وجو داده‌های XMLارايه مي‌دهد. در انتها مثالی از تبدیل داده‌های XML به یك مجموعه با استفاده از فرمت جدید پرس‌وجوی LINQ ارايه داده مي‌شود.
پرس‌وجوی XML
هدف اصلی خانواده فناوری LINQ اضافه نمودن امكانات پرس‌وجو به چارچوب .NET است تا به وسیله آن قادر به پرس‌وجوی تمام منابع اطلاعاتی (از جمله پايگاه‌داده‌های رابطه‌اي و XML) با استفاده از رويكردی واحد باشیم. به دلیل ساختار كلی پرس‌وجو، مي‌توان از LINQ جهت پرس‌وجوی هر كلاس تا زمانی كه IEnumerable<T> را محقق[2] (http://sayan.ir/ViewArticle.aspx?ArticleID=150#_ftn2) كرده باشد استفاده كرد. این بدان معنا نیز هست كه مي‌توان از هر زبان مبتني بر‌.NET با Linq كار كرد. (در حال تنها حاضر به C# و VB.NET اضافه شده‌اند) ، زیرا LINQ API چیزی جز مجموعه‌اي از كلاس‌های.NET نیست.
XLinq زبان پرس‌وجوی XMLاست كه بر اساس پرس‌وجوی LINQمی‌باشد. مي‌توان از آن برای پرس‌وجوی XElement ، XDocument و غیره با استفاده از امكانات پرس‌وجوی LINQ استفاده كرد.
انجام یك پرس‌وجوی ساده
اين هم يك فایل XMLساده كه Products.xml نامیده شده و از آن به عنوان سند اصلی قابلیت‌های پرس‌وجوی توضیح داده شده در این مقاله استفاده مي‌شود. (كد اصلي اين فايل را از طریق اين پيوند (http://www.devx.com/dotnet/Article/32209/0#codeitemarea)دريافت كنيد.)

<?xml version="1.0" encoding="utf-8" ?>
<Products>
<Product ID="1">
<Name>Adjustable Race</Name>
<Number>AR-5381</Number>
</Product>
<Product ID="2">
<Name>Bearing Ball</Name>
<Number>BA-8327</Number>
</Product>
<Product ID="3">
<Name>BB Ball Bearing</Name>
<Number>BE-2349</Number>
</Product>
<Product ID="317">
<Name>LL Crankarm</Name>
<Number>CA-5965</Number>
</Product> Number="" />
<Product ID="318">
<Name>ML Crankarm</Name>
<Number>CA-6738</Number>
</Product>
<Product ID="318">
<Name>ML Crankarm</Name>
<Number>CA-6738</Number>
</Product>
</Products>

kolak2
2007/11/09, 07:16 PM
فایل Products.xml فهرست ساده‌ای از محصولات است كه در آن هر محصول شامل شناسه، نام و شماره مي‌باشد. برای پرس‌وجوی این فایل توسط XLinq ابتدا صفحه ASP.NET به نام SimpleXLinqQuery.asp ایجاد كنید و سپس محتویات صفحه را مانند ذیل در آن قرار دهید.

<%@ Page Language="C#" %>
<%@ Import
Namespace="System.Data.DLinq" %>
<%@ Import
Namespace="System.Data.SqlClient" %>
<%@ Import
Namespace="System.Xml.XLinq" %>
<%@ Import
Namespace="System.Expressions" %>
<%@ Import
Namespace="System.Query" %>
<%@ Import
Namespace="System.Web.Configuration" %>

<script runat="server">
void btnAllGetProductNames_Click
(object sender, EventArgs e)
{
XElement products =
XElement.Load(Server.MapPath
("~/App_Data/Products.xml"));
var productNames = from prod in
products.Elements("Product")
orderby (string) prod.Element("Name")
select (string) prod.Element("Name");
gridResult.DataSource = productNames;
gridResult.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Simple XLinq Query</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button runat="Server"
Text="Get All Product Names"
ID="btnAllGetProductNames"
OnClick="btnAllGetProductNames_Click"/>
<br /><br/>
<asp:GridView runat="server"
ID="gridResult" />
</div>
</form>
</body>
</html>

در بالای صفحه مي‌توانید عبارات مهم تمام نام‌فضاها[3] (http://sayan.ir/ViewArticle.aspx?ArticleID=150#_ftn3) را مشاهده كنید. یكی از نام‌فضاهاي كلیدی System.Query است كه كلاس‌هایی با قدرت پرس‌وجوی بالا به وجود مي‌آورد. مثال زیر به ما نشان مي‌دهد چگونه تمام اسامی تولید شده را به فایل Products.xml برگردانیم.
یك دكمه و GridView به صفحه ASP.NET اضافه كنید. با استفاده از متد Load() كلاس XElement ، فایل XML را در حافظه بار كنید.
XElement products =
XElement.Load(Server.MapPath
("~/App_Data/Products.xml"));

پس از بار كردن فایل XML تمام اسامی تولیدی را بازیابی مي‌كنیم.

var productNames = from prod in
products.Elements("Product")
orderby (string) prod.Element("Name")
select (string) prod.Element("Name");



http://sayan.ir/ShowImage.aspx?ID=246
شكل 1- خروجی اسامی تولیدی
خروجی XLinqQuery.aspx كه نشان‌دهنده اسامی تولیدی بازیابی شده از فایل Products.xml است.

خط پیشین انجام قسمت اعظمی از كار را بر عهده دارد. اكنون به توضیح مفصل آن مي‌پردازیم.
كليدواژه var نشان مي‌دهد كه شما از ویژگی نوع جدید متغیر در چارچوب .NET 3.0 استفاده كرده‌اید. این كليدواژه با كليدواژه مشابه در جاوااسكريپت (كه متغیری را كه قادر به نگهداري هر نوع داده است تولید مي‌كند) تفاوت دارد. كليدواژه var در چارچوب .NET 3.0 به كامپايلرC# دستور مي‌دهد تا نوع را با توجه به ارزش كار محوله تعیین كند.
در سمت راست علامت مساوی، كد برنامه از دستور زبان from..selectبرای پرس‌وجوی فایلXML استفاده مي‌كند. این عبارت تمام عوامل <Name> از عوامل <Product> درفایل Products.xml انتخاب كرده و آنها را به صورت مجموعه‌ای از اسامی تولید شده بر می‌گرداند.
شرط orderby نمونه‌های موجود در مجموعه را ،كه شامل محتویات عامل Name بوده و پیش از مرتب شدن نتایج به مجموعه ارجاع داده مي‌شوند، مرتب مي‌كند.
با در دست داشتن فهرست اسامی تولید شده مي‌توان به‌راحتی آن را به وسیله مرتب كردن منبع داده‌ها به یك GridView متصل كرد. (شكل 1 را مشاهده كنید).

gridResult.DataSource = productNames;
gridResult.DataBind();


استفاده از عملگر “Where”
علاوه بر عملگرهای ساده‌ای كه تاكنون مشاهده كرده‌اید، XLinq دارای عملگر‌های مهمی مانند “Where” است كه امكان ***** كردن نتایج پرس‌وجو‌ها را بر اساس شرط تعیین شده فراهم مي‌كند. جهت نشان دادن این مورد، یك فیلد متن به نام txtValue و یك دكمه به نام btnGetProductNameForID به صفحه اضافه كنید. همان طور كه از اسم دكمه پیداست، كلیك كردن روی این دكمه اسم محصول را برای شناسه خاصی بازیابی مي‌كند. كدی كه در نتیجه این عمل ایجاد مي‌شود به شرح زیر است:

void btnGetProductNameForID_Click
(object sender, EventArgs e)
{
XElement products = XElement.Load
(Server.MapPath
("~/App_Data/Products.xml"));

var productNames = from prod in
products.Elements("Product")
where (string)prod.Attribute("ID")
== txtValue.Text
select (string) prod.Element("Name");

gridResult.DataSource = productNames;
gridResult.DataBind();
}
در مثال فوق، هر گاه كاربر شناسه‌ای از محصول را در فیلد txtValue text وارد كرده و روی دكمه كلیك مي‌كند، عملگر “Where” اسمی را كه مطابق شناسه محصول است برای محصول انتخاب مي‌كند. شكل 2 چگونگی عملكرد مثال فوق را نشان مي‌دهد.
استفاده از عملگر "Take"
این عملگر، همانند عملگر “Where” امكان انتخاب تمامی عناصر را پیش از هر موقعیت ایجاد شده‌ای فراهم مي‌كند. برای مثال كد زیر نشان مي‌دهد چگونه پنج اسم محصول را از فایل Products XML انتخاب كنیم.

یادداشت نویسنده: علی رغم این كه دستور زبان عملگر "where" از دستور زبان عملگر "Take"، كه مسلما یك متد است، متفاوت مي‌باشد اسناد موجود هر دوی آنها را عملگر مي‌نامند. بنابراین، من هم از آن اسناد پیروی كرده و واژه عملگر را برای آنها استفاده كرده‌ام.



http://sayan.ir/ShowImage.aspx?ID=247 (javascript:showSupportItem('figure3');)
شكل 3- ***** كردن پنج اسم اول محصولات
صفحه فوق در مرورگر نشان‌دهنده پنج اسم اول در فهرست محصولات است.

void btnGetTop5ProductNames_Click
(object sender, EventArgs e)
{
XElement products = XElement.Load
(Server.MapPath
("~/App_Data/Products.xml"));

var productNames = (from prod in
products.Elements("Product")
orderby (string) prod.Element("Name")
select (string)
prod.Element("Name")).Take(5);

gridResult.DataSource = productNames;
gridResult.DataBind();
}

چگونگی ایجاد صفحه مثال فوق به طور مفصل توضیح داده نمی‌شود، ولی با مشاهده شكل 3 به راحتی مي‌توان به آن پی برد.
توجه داشته باشید كه استفاده از عملگر Takeدر پایان پرس‌وجو چگونه خروجی توليد شده به وسیله پرس‌وجو را تغییر مي‌دهد و این قدرت LINQ را در زبان پرس‌وجو نمایان مي‌سازد.
به همين روش، مي‌توان فهرست منحصر به فرد اسامی محصولات را با استفاده از عملگر‌های متفاوت به دست آورد.

var productNames =
(from prod in
products.Elements("Product")
orderby (string) prod.Element("Name")
select (string)prod.Element
("Name")).Distinct();


عملگر Distinct اسامی تكراری محصولات را از خروجی حاصله حذف مي‌كند. علاوه بر عملگر‌های Where، Takeو همچنین عملگر‌های متفاوت كه تا كنون معرفی شده‌اند، LINQ عملگر‌های دیگری را هم معرفی كرده است كه مهم‌ترین آنها در جدول 1 نشان داده شده‌اند.



عملگر
توضیحات
Select
مقدار بازگشتی را برای پرس‌وجو مشخص مي‌كند.
where
امكان ***** كردن خروجی را ایجاد مي‌نماید.
First
نخستین عضو را از فهرست حاصله بازیابی مي‌كند.
ElementAt
به شما امكان مي‌دهد تا به عضوي به‌خصوص در محلي به‌خصوص دسترسی یابید.
Take
دسترسی به اعضا را پیش از محلي به‌خصوص ممكن مي‌سازد.
Skip
دسترسی به اعضا را پس از محلي به‌خصوص ممكن مي‌سازد.
ToDictionary
به شما امكان مي‌دهد تا نتایج را در فهرستی با ارزش دوكلیدی برگردانید.
Orderby
فهرست حاصله را به صورت صعودي مرتب مي‌كند.
orderbyDescending
فهرست حاصله را به صورت نزولي مرتب مي‌كند.
Reverse
امكان برعكس كردن ترتیب را فراهم مي‌كند.
Distinct
امكان ***** كردن عناصر تكراری را فراهم مي‌كند.
ToList
امكان برگرداندن نتایج را به صورت فهرستی كه توسط List<T> نمایش داده مي‌شود فراهم مي‌كند.
Except
امكان ***** كردن عناصر متعلق به یك مجموعه خاص را فراهم مي‌كند.


جدول 1- سیستم عامل‌های استاندارد پرس‌وجو: جدول ذیل سیستم عامل‌های مورد استفاده در پرس‌وجو اشیایی كه بر اساس IEnumerable هستند را نشان مي‌دهد.

kolak2
2007/11/09, 07:18 PM
تغيير شكل XML به وسیله XLinq
اكنون از چگونگی پرس‌وجوی فایل XML با استفاده از عملگر‌های پرس‌وجوی آگاهی دارید، اما ممكن است مایل باشید XMLرا پرس‌وجو كرده و نتایج را مستقیما به اشیایی كه قابل انتقال به سرویس‌های دیگري برای انجام عملیات بیشتر باشند، تبديل كنيد. با استفاده از XLinq تبدیل XML به اشیا، كاری بسیار ساده است كه اغلب نیازمند یك خط كد مي‌باشد.
برای روشن‌تر كردن این موضوع به شما نشان خواهم داد كه چگونه فایل Products.xml را پرس‌وجو كرده و محتویات آن را به مجموعه‌ای از اشیای ProductInfo متصل به كنترل GridView تغییر دهید. فهرست 1 كد كامل صفحه را نشان مي‌دهد ولی نكته جالب توجه این جاست كه برای بازگرداندن تمامی عوامل <Product> داخل عامل <Products> ، از متد Descendants()متعلق به شي XElement استفاده مي‌كنیم:

var productInfos = from prod in
products.Descendants("Product")
orderby (string) prod.Element("Name")
select new ProductInfo
{
ProductID = (int)prod.Attribute("ID"),
ProductName = (string)prod.Element("Name"),
ProductNumber = (string)prod.Element("Number")
};

پس از در دست داشتن تمامی عوامل <Product>، مي‌توانید از آنها برای پر كردن مجموعه ProductInfo استفاده كنید. عملیات به این صورت است: مي‌توانید نمونه‌اي از شی ProductInfo ايجاد كرده و مشخصه‌های عمومی آنها را با استفاده از دستور زبان آغازگر جدید و موجود در .NET Framework 3.0 به عنوان قسمتی از عملگر select در نظر بگیرید. با استفاده از این دستور زبان جدید، همان طور كه قبلا گفته شد، مي‌توانید فقط با استفاده از یك خط كد، نمونه جدیدی از شي را ايجاد كرده و مشخصه‌های آن را بر اساس ارزش‌های متناسب تعيين كنيد.
همان طور كه حدس مي‌زنید كلاس ProductInfo كه در مثال قبل از آن استفاده كردیم، بسیار ساده بوده و سه مشخصه عمومی را نشان مي‌داد: شناسه محصول، نام محصول و شماره محصول.

using System;
public partial class ProductInfo
{
private int _productID;
private string _productName;
private string _productNumber;


http://sayan.ir/ShowImage.aspx?ID=248 (javascript:showSupportItem('figure4');)
شكل 4- تبديل شي XML
خروجي توليد شده از تبديل XML به شي ProductInfo و چسباندن آن به يك كنترل GridView

public ProductInfo(){}

public int ProductID
{
get{return _productID;}
set{_productID = value;}
}

public string ProductName
{
get{return _productName;}
set{_productName = value;}
}

public string ProductNumber
{
get{return _productNumber;}
set{_productNumber = value;}
}
}

كلاس ProductInfo را مستقیما در پوشه App_Code پروژه خود قرار دهید و سپس صفحه را به وسیله مرورگر هدایت كنید. خروجی نشان داده شده در شكل 4 را مشاهده خواهید كرد.