عبارت from

عبارت from منبع داده ای که می خواهید داده ای از آن دریافت کنید را تعریف می کند. این عبارت مسئول بدست آوردن عناصر یک منبع داده است. این عبارت در ابتدای یک عبارت پرس وجو می آید، بنا براین کل عبارت پرس و جو پس از آن ، نوع داده ای که بر روی آن کار می کنند را می داند. این کار باعث می شود Visual Studio از ویژگی Intellisense بعد از این عبارت بهره مند شود زیرا نوع تک تک اعضای منبع داده را می داند. در زیر شکل کلی این عبارت را مشاهده می کنید :

from dataType rangeVar in dataSource

این عبارت با کلمه کلیدی from شروع می شود که جز Contextual Ketwords در سی شارپ است. سپس باید یک متغیر موقت که تک تک اعضای یک مجموعه به ترتیب در آن قرار می گیرند را تعریف کنیم. همچنین شما می توانید نوع متغیر موقت را صریحا مشخص کنید که کاربرد خاص خود را دارد . بعد از اعلان متغیر موقت کلمه کلیدی in همراه با نام منبع داده ای که رابط IEnumerable یا IEnumerable را پیاده سازی می کند قرار می گیرد. چیزی که در یک پرس و جوی ساده from اتفاق می افتد این است که این عبارت به ترتیب اعضای مجموعه را در متغیر موقت قرار می دهد. شما می توانید عملیات بیشتری را روی این متغیر مانند بررسی کردن یک شرط خاص انجام دهید. در LINQ قابلیتی به نام deferred execution (اجرای با تعویق) وجود دارد. به این معنی است که LINQ اجرا نمی شود مگر زمانی که با استفاده از حلقه foreach از نتیجه پرس وجو درخواست داده ای را می کنید. در زیر مثالی از عبارت from را مشاهده می کنید :

from int number in numbers

عبارت from بالا به کامپیوتر دستور می دهد که تک تک اعداد داخل یک مجموعه عددی را بر گرداند(با این فرض که آن مجموعه یک آرایه یا شی ای است که رابطIEnumerable را پیاده سازی می کند ). به نوع متغیر موقت در مثال بالا توجه کنید . در بیشتر مواقع ، اگر از نوع داده های منبع داده مطمئن هستید می توانید از نوشتن این نوع صرف نظر کنید.

from number in numbers

کامپایلر می تواند به صورت خودکار و بسته به نوع داده های منبع داده ، نوع متغیر موقت را تشخیص دهد. به عنوان مثال اگر مجموعه ای داریم که رابط IEnumerable را پیاده سازی کرده است ، نوع متغیر موقت به طور خودکار Person در نظر گرفته می شود. اما اگر قصد پرس و جو در مجموعه ای از اشیا مانند ArrayList را دارید بهتر آن است که نوع متغیر موقت که بیانگر نوع عناصر داخل مجموعه است را صریحا مشخص نمایید . مثال زیر را در نظر بگیرید :

ArrayList persons = new ArrayList();
persons.Add(new Person("John", "Smith"));
persons.Add(new Person("Mark", "Chandler"));
persons.Add(new Person("Eric", "Watts"));

var query = from p in persons
            select p;

اگر مثال بالا را کامپایل کنید با خطای زیر مواجه می شوید :

Could not find an implementation of the query pattern for source type 
'System.Collections.ArrayList'.  'Select' not found.  Consider explicitly specifying the 
type of the range variable 'p'.

به این خاطر که ArrayList میتواند شامل اشیا از نوع های مختلفی باشد. کامپایلر توصیه می کند که نوع عناصر مجموعه را صریحا مشخص کنید. برای حل مشکل بالا کافی است نوع متغیر موقت را به شکل زیر مشخص کنید :

from Person p in persons

LINQ برای انجام پرس جو هر کدام از اعضای مجموعه را به نوع Person تبدیل می کند. اگر شی ای از مجموعه پیدا شود که قابل تبدیل به نوع Person نباشد یک استثنا رخ می شود. عبارت from در ابتدای یک عبارت پرس وجو می آید این کار به Visual Studio امکان می دهد که نوع داده هایی که بر روی آنها کار می کنید را تشخیص دهد. همانطور که از شکل زیر پیداست ، بعد از عبارت from می توانید از مزایای Intellisense بهره مند شوید.
from-clause-1001

 

وصل کردن چندین جدول از طریق چندین عبارت from

اگر شما 2 منبع داده در اختیار دارید ، می توانید با استفاده از چند عبارت from آنها را به همدیگر وصل کنید. مثال زیر را که باعث اتصال دو مجموعه از اعداد می شود را در نظر بگیرید :

int[] numberSet1 = { 1, 2, 3, 4, 5 };
int[] numberSet2 = { 6, 7, 8, 9, 10 };

var query = from n1 in numberSet1 
            from n2 in numberSet2 
            select String.Format("{0},{1}", n1, n2); 

foreach (var n in query)
{
    Console.WriteLine(n.ToString());
}
(1,6)
(1,7)
(1,8)
(1,9)
(1,10)
(2,6)
(2,7)
(2,8)
(2,9)
(2,10)
(3,6)
(3,7)
(3,8)
(3,9)
(3,10)
(4,6)
(4,7)
(4,8)
(4,9)
(4,10)
(5,6)
(5,7)
(5,8)
(5,9)
(5,10)

در مثال بالا از دو عبارت from که داده ها را از دو منبع مختلف واکشی می کنند استفاده کرده ایم. در انتها با استفاده از متد Format خروجی را فرمت بندی کرده ایم. همانطور که در خروجی می بینید ، هر نوع ترکیب ممکن در خروجی پرس وجو قرار گرفته است ( ضرب دکارتی). به این ترکیب اصطلاحا inner join گفته می شود. همچنین شما می توانید مستقیما از عبارت join که بعدا توضیح داده می شود استفاده کنید. به این نکته توجه کنید که لزومی ندارد عبارت from دوم و سوم مستقیما بعد از عبارت from اول قرار گیرند. شما می توانید از پرس وجویی به شکل زیر استفاده کنید :

from n1 in numberSet1
where n1 > 2
from n2 in numberSet2
select String.Format("({0},{1})", n1, n2);

یک عبارت from تکی، معادل متدی در فضای نامی System.LINQ ندارد. شما می توانید از متد Select() و دیگر متد ها استفاده کنید . ولی برای چند عبارت from می توانید از متد SelectMany() که در درس های بعدی به آن پرداخته می شود استفاده کنید .

 

ساخت ارتباط بر روی کلاس ها

عبارات پرس و جوی متشکل از چند عبارت from می توانند به شکل موثری در کلاس های مرتبط استفاده شوند. اما چنین کلاس هایی ابتدا باید به شکل مطلوب ساختار بندی شوند. به عنوان مثال یک مشتری می تواند چندین سفارش داشته باشد که این رابطه را می توان به عنوان یک رابطه یک به چند در نظر گرفت ( یک مشتری با چندین سفارش) اجازه دهید ابتدا کلاس مشتری و سفارش را به شکل مناسب تعریف کنیم :

class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<Order> Orders { get; set; }
}

برای سادگی مثال ، کلاس مشتری از 3 خاصیت تشکیل شده است. خاصیت سوم رابطه کلاس مشتری با کلاس سفارش را تعریف می کند. این خاصیت شامل لیست سفارش های مشتری است. کلاس سفارش در زیر تعریف شده است.

class Order
{
    public string Name { get; set; }
    public int Quantity { get; set; }
}

اجازه دهید چند شی مشتری ایجاد کرده و چند سفارش را به خاصیت Orders آنها اختصاص دهیم.

   1: class Program                                                                      
   2: {                                                                                  
   3:     static void Main(string[] args)                                                
   4:     {                                                                              
   5:         List<Customer> customers = new List<Customer>();               
   6:                                                                                    
   7:         Customer customer1 = new Customer()                                        
   8:         {                                                                          
   9:             FirstName = "John",                                                    
  10:             LastName = "Smith",                                                    
  11:             Orders = new List<Order>()                                       
  12:             {                                                                      
  13:                 new Order() { Name = "Pizza", Quantity = 5 },                      
  14:                 new Order() { Name = "Chicken", Quantity = 3 },                    
  15:                 new Order() { Name = "Salad", Quantity = 7 }                       
  16:             }                                                                      
  17:         };                                                                         
  18:                                                                                    
  19:                                                                                    
  20:         Customer customer2 = new Customer()                                        
  21:         {                                                                          
  22:             FirstName = "Allan",                                                   
  23:             LastName = "York",                                                     
  24:             Orders = new List<Order>()                                       
  25:             {                                                                      
  26:                 new Order() { Name = "Orange Juice", Quantity = 2 },               
  27:                 new Order() { Name = "Soda", Quantity = 4 }                        
  28:             }                                                                      
  29:         };                                                                         
  30:                                                                                    
  31:         Customer customer3 = new Customer()                                        
  32:         {                                                                          
  33:             FirstName = "Henry",                                                   
  34:             LastName = "Helms",                                                    
  35:             Orders = new List<Order>()                                       
  36:             {                                                                      
  37:                 new Order() { Name = "Speghetti", Quantity = 7 },                  
  38:                 new Order() { Name = "Nachos", Quantity = 13 }                     
  39:             }                                                                      
  40:         };                                                                         
  41:                                                                                    
  42:         customers.Add(customer1);                                                  
  43:         customers.Add(customer2);                                                  
  44:         customers.Add(customer3);                                                  
  45:                                                                                    
  46:         var results = from c in customers                                        
  47:                       from o in c.Orders                                         
  48:                       select new { c.FirstName, c.LastName, o.Name, o.Quantity };
  49:                                                                                    
  50:         foreach (var result in results)                                            
  51:         {                                                                          
  52:             Console.WriteLine("Name: {0} {1}, Order: {2}, Quantity: {3}",          
  53:                 result.FirstName, result.LastName, result.Name, result.Quantity);  
  54:         }                                                                          
  55:     }                                                                              
  56: }
Name: John Smith, Order: Pizza, Quantity: 5
Name: John Smith, Order: Chicken, Quantity: 3
Name: John Smith, Order: Salad, Quantity: 7
Name: Allan York, Order: Orange Juice, Quantity: 2
Name: Allan York, Order: Soda, Quantity: 4
Name: Henry Helms, Order: Speghetti, Quantity: 7
Name: Henry Helms, Order: Nachos, Quantity: 13

همانطور که در خروجی می بینید ، سفارشات تمامی مشتریان نشان داده شده است. همچنین برای مرتب کردن خروجی می توان از عملگر group-by استفاده کرد. در خط 40-7 در مثال قبل ، 3 شی Customer ایجاد کرده ایم که هر کدام دارای سفارشات مخصوص به خود هستند . سپس هر کدام از این 3 شی را به لیست مشتریان اضافه کرده ایم. خطوط 48-46 پرس وجویی با 2 عبارت from را نشان می دهد. اولین عبارت from یک شی Customer را از لیست مشتریان انتخاب می کند. دومین عبارت from تک تک اعضای خاصیت Orders مشتری انتخاب شده را بر می گرداند. عبارت select با استفاده از projection نام و نام خانوادگی مشتری ، نام و تعداد سفارش را انتخاب می کند. خطوط 54-50 نتیجه را در خروجی چاپ می کنند.

طراحی کلاس ها به شکل بالا بسیار مناسب است زیرا تشخیص ارتباط بین اشیا به راحتی امکان پذیر است. جداول موجود در پایگاه داده معمولا از این نوع ارتباطات استفاده می کنند. ابزارهایی در Visual Studio وجود دارند که جدوال و ارتباطات بین آنها را به کلاس ها و ارتباط بین آنها تبدیل می کنند.در مبحث LINQ To SQL به این امر پرداخته شده است.

لطفا اگر نظر، پیشنهاد و یا انتقادی در باره مطلب بالا دارید در قسمت زیر و اگر سوالی دارید در بخش پرسش و پاسخ مطرح بفرمایید.

  1. ابراهیم پاسخ دادن

    سلام ممنون خیلی ساده و روان توضیح میدین اگه امکان داره مطالب این بخش رو زیاد کنید ممنون

    • یونس ابراهیمی پاسخ دادن

      سلام دوست عزیز…در حال آماده کردن مطالب جدیدم

  2. ابراهیم پاسخ دادن

    ممنوم از زحماتتون موفق و موید باشید یه سوال داشتم در مورد لینک با پایگاه داده در سی شارپ روش استفاده استوور پروسیجر با کینک در سی شارپ بهتر است یا از استور پروسیجر در سی شارپ استفاده نکنم کدوم روش را پیشنهاد میکنید؟

  3. یونس ابراهیمی پاسخ دادن

    استور پروسیجر با LINQ چون کدنویسی کمتری لازم داره.

  4. ابراهیم پاسخ دادن

    با سلام ممنون ازتون

  5. aminmh پاسخ دادن

    خیلی عالی بود مرسی

    • یونس ابراهیمی پاسخ دادن

      خواهش می کنم دوست عزیز…ممنون از اینکه نظر دادین