Klauzula join (odwołanie w C#)
join Klauzuli jest przydatny do kojarzenia elementów z sekwencji innego źródła, które nie mają bezpośredniego relacji w modelu obiektów.Jedynym wymogiem jest, że elementy w każdym źródle udziału pewną wartość, które można porównać do równości.Na przykład dystrybutora żywności może mieć listę dostawców niektórych produktów i Lista nabywców.A join klauzuli można, na przykład, aby utworzyć listę dostawców i nabywców tego produktu, którzy są w tym samym określonego regionu.
A join klauzuli trwa dwa źródła sekwencji jako danych wejściowych.Elementy w każdej sekwencji muszą znajdować się albo zawiera właściwość, która może być porównywana z odpowiednia właściwość w innych sekwencji.join Klauzuli porównuje określony kluczy dla równości przy użyciu specjalnych equals słowa kluczowego.Wszystkie sprzężenia wykonywane przez join klauzuli są equijoins.Kształt produkcji join klauzuli zależy od określonego typu sprzężenia są wykonywane.Poniżej przedstawiono trzy najbardziej popularne typy sprzężeń:
Sprzężenie wewnętrzne
Grupa sprzężenia
Lewe sprzężenie zewnętrzne
Sprzężenie wewnętrzne
W poniższym przykładzie przedstawiono prosty equijoin wewnętrznym.Ta kwerenda produkuje płaski sekwencji "Nazwa produktu / kategorii" pary.Ten sam ciąg kategorii będą wyświetlane w wielu elementów.Jeśli element z categories jest brak odpowiedniego products, tej kategorii nie będą wyświetlane w wynikach.
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence
Aby uzyskać więcej informacji, zobacz Porady: wykonanie sprzężeń wewnętrznych (Przewodnik programowania w języku C#).
Grupa sprzężenia
A join klauzuli z into wyrażenie jest nazywany sprzężenia grupy.
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
Sprzężenie grupy produkuje sekwencji hierarchiczne wynik kojarzy elementy w kolejności lewej źródła z pasujących elementów sekwencji źródła po prawej stronie.Sprzężenie grupy nie ma odpowiednika w relacyjnych warunkach; jest zasadniczo sekwencji tablic obiektu.
Jeżeli stwierdzono żadnych elementów z sekwencji źródłowego odpowiadają element w lewym źródła, join klauzuli da pustą tablicę dla tego elementu.W związku z tym sprzężenia grupy jest nadal zasadniczo są sprzężenie wewnętrzne, chyba że sekwencja wyników są zorganizowane w grupy.
Jeśli wystarczy wybrać wyniki sprzężenia grupy uzyskują dostęp do elementów, ale nie może zidentyfikować odpowiadającej na klucz.Dlatego jest zwykle bardziej przydatne wybrać wyniki sprzężenia grupy do nowego typu, który ma również nazwę klucza, jak pokazano w poprzednim przykładzie.
Oczywiście, umożliwia także wynikiem sprzężenia grupy jako generatora dostępnego w innej podkwerendzie:
var innerGroupJoinQuery2 =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from prod2 in prodGroup
where prod2.UnitPrice > 2.50M
select prod2;
Aby uzyskać więcej informacji, zobacz Porady: wykonanie sprzężeń grupowanych (Przewodnik programowania w języku C#).
Lewe sprzężenie zewnętrzne
W lewe sprzężenie zewnętrzne zwracane są wszystkie elementy w kolejności lewej źródła, nawet jeśli nie pasujące elementy są w odpowiedniej kolejności.Aby wykonać lewe sprzężenie zewnętrzne, w LINQ, użyj DefaultIfEmpty metody w połączeniu z sprzężenia grupy, aby określić domyślny element po prawej stronie, do produkcji, jeśli element po lewej stronie nie ma żadnych dopasowań.Można użyć null jako wartości domyślnej dla odwołania do dowolnego typu, lub można określić typ domyślne zdefiniowane przez użytkownika.W poniższym przykładzie przedstawiono zdefiniowane przez użytkownika domyślnego typu:
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product { Name = String.Empty, CategoryID = 0 })
select new { CatName = category.Name, ProdName = item.Name };
Aby uzyskać więcej informacji, zobacz Porady: wykonanie lewych sprzężeń zewnętrznych (Przewodnik programowania w języku C#).
Operator równości
A join klauzuli wykonuje sprzężenie.Innymi słowy można tylko podstawowy dopasowań na równość dwa klucze.Inne rodzaje porównań, takie jak "większy niż" lub "nie równa się" nie są obsługiwane.Wyjaśnienie, że wszystkie sprzężenia są equijoins, join korzysta z klauzuli equals słowa kluczowego zamiast == operatora.equals Słowa kluczowego mogą być używane tylko w join klauzuli i różni się od == operatora w jeden istotny sposób.Z equals, lewy klawisz zużywa sekwencji zewnętrzne źródła i prawego klawisza używa wewnętrznego źródła.Zewnętrzne źródło jest jedynie w zakresie, w lewej części equals i sekwencja źródła wewnętrzna jest jedynie w zakresie po prawej stronie.
Nie Equijoins
Non-equijoins, sprzężenia i innych operacji join niestandardowych można wykonać przy użyciu wielu from klauzul wprowadzenie nowej sekwencji, niezależnie do kwerendy.Aby uzyskać więcej informacji, zobacz Porady: wykonywanie niestandardowych operacji łączenia (Przewodnik programowania w języku C#).
Przyłącza się na obiekt kolekcje vs.tabele relacyjne
W LINQ wyrażenie kwerendy, sprzężenia operacje są wykonywane na kolekcji obiektów.Dołączył kolekcji obiektów nie może być "do" w dokładnie taki sam sposób jak dwie tabele relacyjnej.W LINQ, jawnych join klauzule są tylko wymagane podczas dwóch sekwencji źródła nie są powiązane przez wszelkie relacje.Podczas pracy z LINQ do SQL, tabele klucza obcego są reprezentowane w modelu obiektów jako właściwości tabeli podstawowej.Na przykład w bazie danych Northwind tabeli Nabywca ma relacja klucza obcego z tabeli zamówienia.Podczas mapowania tabel do modelu obiektowego, klasa klienta ma właściwość zamówienia, który zawiera kolekcję zleceń produkcyjnych skojarzonych z tego klienta.W efekcie sprzężenie zostało uczynione dla Ciebie.
Aby uzyskać więcej informacji na temat kwerend w tabelach powiązanych relacją w kontekście LINQ do SQL, zobacz How to: Map Database Relationships.
Klucze kompozytowe
Można sprawdzić równości wiele wartości, przy użyciu klucza złożonego.Aby uzyskać więcej informacji, zobacz Porady: sprzęganie za pomocą kluczy złożonych (Przewodnik programowania w języku C#).Projekt wstępny klucze mogą być również używane w group klauzuli.
Przykład
Poniższy przykład porównuje wyniki sprzężenie wewnętrzne, sprzężenia grupy i lewe sprzężenie zewnętrzne na te same źródła danych przy użyciu tych samych klawiszy pasujących.Dodatkowy kod zostanie dodany do tych przykładów, aby wyjaśnić wyniki na ekranie konsoli.
class JoinDemonstration
{
#region Data
class Product
{
public string Name { get; set; }
public int CategoryID { get; set; }
}
class Category
{
public string Name { get; set; }
public int ID { get; set; }
}
// Specify the first data source.
List<Category> categories = new List<Category>()
{
new Category(){Name="Beverages", ID=001},
new Category(){ Name="Condiments", ID=002},
new Category(){ Name="Vegetables", ID=003},
new Category() { Name="Grains", ID=004},
new Category() { Name="Fruit", ID=005}
};
// Specify the second data source.
List<Product> products = new List<Product>()
{
new Product{Name="Cola", CategoryID=001},
new Product{Name="Tea", CategoryID=001},
new Product{Name="Mustard", CategoryID=002},
new Product{Name="Pickles", CategoryID=002},
new Product{Name="Carrots", CategoryID=003},
new Product{Name="Bok Choy", CategoryID=003},
new Product{Name="Peaches", CategoryID=005},
new Product{Name="Melons", CategoryID=005},
};
#endregion
static void Main(string[] args)
{
JoinDemonstration app = new JoinDemonstration();
app.InnerJoin();
app.GroupJoin();
app.GroupInnerJoin();
app.GroupJoin3();
app.LeftOuterJoin();
app.LeftOuterJoin2();
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
void InnerJoin()
{
// Create the query that selects
// a property from each element.
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { Category = category.ID, Product = prod.Name };
Console.WriteLine("InnerJoin:");
// Execute the query. Access results
// with a simple foreach statement.
foreach (var item in innerJoinQuery)
{
Console.WriteLine("{0,-10}{1}", item.Product, item.Category);
}
Console.WriteLine("InnerJoin: {0} items in 1 group.", innerJoinQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupJoin()
{
// This is a demonstration query to show the output
// of a "raw" group join. A more typical group join
// is shown in the GroupInnerJoin method.
var groupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select prodGroup;
// Store the count of total items (for demonstration only).
int totalItems = 0;
Console.WriteLine("Simple GroupJoin:");
// A nested foreach statement is required to access group items.
foreach (var prodGrouping in groupJoinQuery)
{
Console.WriteLine("Group:");
foreach (var item in prodGrouping)
{
totalItems++;
Console.WriteLine(" {0,-10}{1}", item.Name, item.CategoryID);
}
}
Console.WriteLine("Unshaped GroupJoin: {0} items in {1} unnamed groups", totalItems, groupJoinQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupInnerJoin()
{
var groupJoinQuery2 =
from category in categories
orderby category.ID
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new
{
Category = category.Name,
Products = from prod2 in prodGroup
orderby prod2.Name
select prod2
};
//Console.WriteLine("GroupInnerJoin:");
int totalItems = 0;
Console.WriteLine("GroupInnerJoin:");
foreach (var productGroup in groupJoinQuery2)
{
Console.WriteLine(productGroup.Category);
foreach (var prodItem in productGroup.Products)
{
totalItems++;
Console.WriteLine(" {0,-10} {1}", prodItem.Name, prodItem.CategoryID);
}
}
Console.WriteLine("GroupInnerJoin: {0} items in {1} named groups", totalItems, groupJoinQuery2.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupJoin3()
{
var groupJoinQuery3 =
from category in categories
join product in products on category.ID equals product.CategoryID into prodGroup
from prod in prodGroup
orderby prod.CategoryID
select new { Category = prod.CategoryID, ProductName = prod.Name };
//Console.WriteLine("GroupInnerJoin:");
int totalItems = 0;
Console.WriteLine("GroupJoin3:");
foreach (var item in groupJoinQuery3)
{
totalItems++;
Console.WriteLine(" {0}:{1}", item.ProductName, item.Category);
}
Console.WriteLine("GroupJoin3: {0} items in 1 group", totalItems, groupJoinQuery3.Count());
Console.WriteLine(System.Environment.NewLine);
}
void LeftOuterJoin()
{
// Create the query.
var leftOuterQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select prodGroup.DefaultIfEmpty(new Product() { Name = "Nothing!", CategoryID = category.ID });
// Store the count of total items (for demonstration only).
int totalItems = 0;
Console.WriteLine("Left Outer Join:");
// A nested foreach statement is required to access group items
foreach (var prodGrouping in leftOuterQuery)
{
Console.WriteLine("Group:", prodGrouping.Count());
foreach (var item in prodGrouping)
{
totalItems++;
Console.WriteLine(" {0,-10}{1}", item.Name, item.CategoryID);
}
}
Console.WriteLine("LeftOuterJoin: {0} items in {1} groups", totalItems, leftOuterQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void LeftOuterJoin2()
{
// Create the query.
var leftOuterQuery2 =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty()
select new { Name = item == null ? "Nothing!" : item.Name, CategoryID = category.ID };
Console.WriteLine("LeftOuterJoin2: {0} items in 1 group", leftOuterQuery2.Count());
// Store the count of total items
int totalItems = 0;
Console.WriteLine("Left Outer Join 2:");
// Groups have been flattened.
foreach (var item in leftOuterQuery2)
{
totalItems++;
Console.WriteLine("{0,-10}{1}", item.Name, item.CategoryID);
}
Console.WriteLine("LeftOuterJoin2: {0} items in 1 group", totalItems);
}
}
/*Output:
InnerJoin:
Cola 1
Tea 1
Mustard 2
Pickles 2
Carrots 3
Bok Choy 3
Peaches 5
Melons 5
InnerJoin: 8 items in 1 group.
Unshaped GroupJoin:
Group:
Cola 1
Tea 1
Group:
Mustard 2
Pickles 2
Group:
Carrots 3
Bok Choy 3
Group:
Group:
Peaches 5
Melons 5
Unshaped GroupJoin: 8 items in 5 unnamed groups
GroupInnerJoin:
Beverages
Cola 1
Tea 1
Condiments
Mustard 2
Pickles 2
Vegetables
Bok Choy 3
Carrots 3
Grains
Fruit
Melons 5
Peaches 5
GroupInnerJoin: 8 items in 5 named groups
GroupJoin3:
Cola:1
Tea:1
Mustard:2
Pickles:2
Carrots:3
Bok Choy:3
Peaches:5
Melons:5
GroupJoin3: 8 items in 1 group
Left Outer Join:
Group:
Cola 1
Tea 1
Group:
Mustard 2
Pickles 2
Group:
Carrots 3
Bok Choy 3
Group:
Nothing! 4
Group:
Peaches 5
Melons 5
LeftOuterJoin: 9 items in 5 groups
LeftOuterJoin2: 9 items in 1 group
Left Outer Join 2:
Cola 1
Tea 1
Mustard 2
Pickles 2
Carrots 3
Bok Choy 3
Nothing! 4
Peaches 5
Melons 5
LeftOuterJoin2: 9 items in 1 group
Press any key to exit.
*/
Uwagi
A join klauzuli, która nie jest stosowana przez into jest tłumaczona na Join``4 wywołanie metody.A join klauzuli, która następuje po into jest tłumaczona na GroupJoin``4 wywołanie metody.
Zobacz też
Zadania
Porady: wykonanie lewych sprzężeń zewnętrznych (Przewodnik programowania w języku C#)
Porady: wykonanie sprzężeń wewnętrznych (Przewodnik programowania w języku C#)
Porady: wykonanie sprzężeń grupowanych (Przewodnik programowania w języku C#)
Porady: kolejność wyników klauzuli join (Przewodnik programowania w języku C#)
Porady: sprzęganie za pomocą kluczy złożonych (Przewodnik programowania w języku C#)
Porady: instalacja przykładowych baz danych
Informacje
group — Klauzula (odwołanie w C#)
Koncepcje
Wyrażenia kwerend LINQ (Przewodnik programowania w języku C#)