عبارت Join – انجام یک عمل Group Join

با استفاده از عبارت join، شما می‌توانید یک اتصال group join را انجام دهید. یک اتصال group join عناصری از منبع داده‌ی داخلی را با استفاده از عنصر نظیر آنها در منبع داده‌ی خارجی را گروه بندی می‌کند. به عنوان مثال، همه‌ی کتاب‌های نوشته شده به وسیله‌ی John Smith گروه بندی می‌شوند، همچنین تمامی کتاب‌های نوشته شده توسط Harry Gold در یک گروه جداگانه قرار می‌گیرند. شکل زیر یک عمل group join نشان می‌دهد.
join-clause-group-1001
همه‌ی عناصر موجود در منبع داده‌ی داخلی که دارای کلیدی مشترک هستند و دارای یک عنصر نظیر در منبع داده‌ی خارجی هستند تشکیل یک گروه را می‌دهند. همانطور که مشاهده می‌کنید، نتیجه‌ی یک اتصال group join کلکسیونی از گروه‌ها هست. هرکدام بیانگر گروهی برای یک کلید خاص می‌باشند. به عنوان مثال، کلید اتصال می‌تواند مؤلف کتاب باشد. می‌توان کتاب‌های هر مؤلف را در گروهی جداگانه قرار داد. در این صورت نتیجه عمل پرس و جو کلکسیونی از گروهها است که هر گروه شامل کتاب‌های نوشته شده توسط یک مؤلف خاص می‌باشد. هر عنصر خارجی (عنصری که در منبع داده‌ی خارجی است) که عنصری نظیر در منبع داده‌ی داخلی ندارد تشکیل یک گروه خالی را می‌دهد و همچنان در لیست نتایج ظاهر می‌شود. به مثال زیر دقت کنید. دو کلاس به نام‌های Author و Book تعریف می‌کنیم.

class Author
{
    public int AuthorId { get; set; }
    public string Name { get; set; }
}

class Book
{
    public int AuthorId { get; set; }
    public string Title { get; set; }
}

عبارت پرس و جوی موجود در مثال زیر از اتصال group join استفاده می‌کند.

   1: Author[] authors = new Author[] 
   2: {
   3:     new Author() { AuthorId = 1, Name = "John Smith" },
   4:     new Author() { AuthorId = 2, Name = "Harry Gold" },
   5:     new Author() { AuthorId = 3, Name = "Ronald Schwimmer" },
   6:     new Author() { AuthorId = 4, Name = "Jerry Mawler" }
   7: };
   8: 
   9: Book[] books = new Book[] 
  10: {
  11:     new Book() { AuthorId = 1, Title = "Little Blue Riding Hood" },
  12:     new Book() { AuthorId = 3, Title = "The Three Little Piggy Banks" },
  13:     new Book() { AuthorId = 1, Title = "Snow Black" },
  14:     new Book() { AuthorId = 2, Title = "My Rubber Duckie" },
  15:     new Book() { AuthorId = 2, Title = "He Who Doesn't Know His Name" },
  16:     new Book() { AuthorId = 1, Title = "Hanzel and Brittle" }
  17: };
  18: 
  19: var result = from a in authors
  20:              join b in books on a.AuthorId equals b.AuthorId into booksByAuthor
  21:              select new { Author = a.Name, Books = booksByAuthor };
  22: 
  23: foreach (var r in result)
  24: {
  25:     Console.WriteLine("Books written by {0}:", r.Author);
  26: 
  27:     foreach (var b in r.Books)
  28:     {
  29:         Console.WriteLine("---{0}", b.Title);
  30:     }
  31: }
Books written by John Smith:
---Little Blue Riding Hood
---Snow Black
---Hanzel and Brittle
Books written by Harry Gold:
---My Rubber Duckie
---He Who Doesn't Know His Name
Books written by Ronald Schwimmer:
---The Three Little Piggy Banks
Books written by Jerry Mawler:

به عبارت join در خط 20 توجه کنید. این عبارت یک کتاب از منبع داده‌ی books را به یک مؤلف در منبع داده‌ی authors به وسیله‌ی خاصیت AuthorId متصل می‌کند. کلمه کلیدی into که بعد از آن متغیر گروه بندی قرار می‌گیرد مشخص می‌کند که عمل اتصال از نوع group join می‌باشد. کلید تمامی عنصرهای داخلی (عناصری که در منبع داده‌ی داخلی قرار دارند) که با کلید عناصر متناظر خارجی خود برابر باشند با یکدیگر ترکیب می‌شوند و تشکیل یک گروه جدید می‌دهند.
عبارت select در خط 21 نتیجه را که شامل نام مؤلف و گروه کتاب‌های متعلق به آن است را در خروجی قرار می‌دهد. نتیجه‌ی عبارت پرس و جو کلکسیونی از گروه‌های کتاب است. حلقه‌ی foreach تودرتو در خطوط 23 تا 31 نتایج عبارت پرس و جو را نشان می‌دهد. در داخل اولین حلقه foreach نام مؤلف نمایش داده می‌شود. در داخل حلقه داخلی تمامی کتاب‌های نوشته شده توسط مؤلف که در خاصیت Books قرار دارند نمایش داده می‌شود. به یاد داشته باشید که این خاصیت کلکسیونی از کتاب‌ها را که به تفکیک مؤلف گروه بندی شده‌اند را در خود قرار می‌دهد. همانطور که در خروجی مشاهده می‌کنید Jerry Mawler هیچ کتابی ننوشته است در نتیجه خاصیت Books خالی است. بنابراین هیچ کتابی نمایش داده نمی‌شود. متد GroupJoin، معادل متدی عبارت group join می‌باشد. معادل متدی مثال بالا به صورت زیر می‌باشد :

var result = authors.GroupJoin(books,
                               author => author.AuthorId,
                               book => book.AuthorId,
                               (author, booksByAuthor) => 
                                   new { Author = author.Name, Books = booksByAuthor });

اولین پارامتر مشخص کننده منبع داده‌ی داخلی است که ما قصد داریم آن را منبع داده‌ی خارجی متصل کنیم. پارامتر دوم یک نماینده است که یک عبارت لامبدا را برای تشخیص کلید خارجی برای عمل الحاق را قبول می‌کند. سومین پارامتر کلید داخلی و پارامتر چهارم برای ایجاد شکل خروجی برای هر گروه می‌باشد.