Sdílet prostřednictvím


join – klauzule (Referenční dokumentace jazyka C#)

join Klauzule je užitečné pro přidružení prvky z různých zdrojů sekvence, které nemají žádný přímý vztah v objektovém modelu.Jediným požadavkem je, že sdílet prvky v jednotlivých zdrojů hodnotu, která lze porovnat pro rovnost.Distributor potravin může mít například seznam dodavatelů určitého produktu a seznam kupujících.A join klauzuli lze použít například k vytvoření seznamu dodavatelů a kupující produktu, kteří jsou ve stejné stanovené pěstitelské oblasti.

A join klauzule trvá dvě sekvence zdroje jako vstup.Prvky v každé řadě musíte být nebo obsahovat vlastnost, kterou lze ve srovnání s odpovídající vlastnost v jiné posloupnosti.join Klauzule porovná určené klíče pro rovnost pomocí zvláštního equals klíčové slovo.Všechna spojení prováděné join klauzule jsou equijoins.Obrazec výstup join klauzule závisí na konkrétní typ spojení, které provádíte.Zde jsou tři nejčastější typy spojení:

  • Vnitřní spojení

  • Skupina spojení

  • Levé vnější spojení.

Vnitřní spojení

Následující příklad ukazuje jednoduchý vnitřní porovnávání.Tento dotaz vytvoří posloupnost flat "název produktu / kategorie" páry.Stejný řetězec kategorie se zobrazí ve více prvků.Pokud prvek z categories má žádné odpovídající products, kategorie se nezobrazí ve výsledcích.

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

Další informace naleznete v tématu Postupy: Provádění vnitřních spojení (Průvodce programováním v C#).

Skupina spojení

A join klauzule s into výrazu se nazývá spojení skupiny.

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 };

Skupiny spojení vytváří hierarchický výsledek sekvence, které prvky v levém zdroj posloupnosti přidruží jeden nebo více prvků odpovídající pořadí zdroje pravé.Spojení skupiny nemá žádný ekvivalent v relační podmínek; je v podstatě posloupnost polí objektu.

Pokud jsou nalezeny žádné prvky z řady vpravo zdroje odpovídající prvek ve zdroji vlevo join klauzule vytvoří prázdné pole pro danou položku.Proto skupiny spojení je stále v podstatě vnitřní porovnávání výsledků sekvence jsou uspořádány do skupin.

Pokud vyberete pouze výsledky skupiny spojení, můžete přistupovat k položkám, ale nelze určit odpovídající na klíč.Proto je obecně užitečnější výsledky skupiny spojení vyberte do nového typu, který má také název klíče, jak je znázorněno v předchozím příkladu.

Samozřejmě můžete také v důsledku spojení skupiny jako generátor jiného poddotazu:

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;

Další informace naleznete v tématu Postupy: Provádění seskupených spojení (Průvodce programováním v C#).

Levé vnější spojení

V levé vnější spojení jsou vráceny všechny prvky v levém zdroj posloupnosti, i v případě, že žádné vyhovující prvky jsou v pravém posloupnosti.K provedení levé vnější spojení v LINQ, použít DefaultIfEmpty metoda v kombinaci s spojení skupiny určit výchozí vpravo prvek vyrábět vlevo prvek má žádné odpovídající položky.Můžete použít null jako výchozí hodnotu pro odkaz typu, nebo zadat výchozí uživatelem definovaný typ.V následujícím příkladu je uvedena uživatelem definované výchozí typ:

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 };

Další informace naleznete v tématu Postupy: Provedení levých vnějších spojení (Průvodce programováním v C#).

Operátor rovná se

A join klauzule provádí porovnávání.Jinými slovy lze pouze základní shody na rovnost dvou klíčů.Jiné typy porovnání jako "větší než" nebo "není rovno" není podporováno.Aby bylo zřejmé, že jsou všechna spojení equijoins, join používá klauzuli equals klíčové místo == operátor.equals Klíčových slov lze použít pouze v join klauzule a že se liší od == operátor jedním důležitým způsobem.S equals, levé klíč spotřebovává sekvence vnější zdroj a pravé klávesy spotřebovává vnitřní zdroj.Vnější zdroj je pouze v oboru na levé straně equals a vnitřní zdroj sekvence je pouze v oboru na pravé straně.

Bez Equijoins

Non-equijoins, křížové spojení a jiné operace vlastní spojení můžete provádět pomocí více from klauzule nezávisle zavést nové sekvence do dotazu.Další informace naleznete v tématu Postupy: Provádění vlastních operací spojování (Průvodce programováním v C#).

Spojení na objekt kolekce vs.relační tabulky

V LINQ výrazu dotazu, spojení, které operace jsou prováděny na objekt kolekce.Objekt kolekce nelze "připojit" stejným způsobem jako dva relační tabulky.V LINQ, explicitní join doložky jsou pouze požadované při dvou řad zdroje nejsou vázány žádné vztahem.Při práci s Technologie LINQ to SQL, tabulky cizího klíče jsou reprezentovány v objektovém modelu vlastnosti primární tabulky.V tabulce Zákazník má v databázi Northwind vztah cizího klíče s tabulkou objednávky.Při mapování tabulek k objektovému modelu, třídy zákazníků má vlastnost objednávky obsahující kolekci objednávky přidružené k tomuto zákazníkovi.Spojení, již bylo provedeno automaticky.

Další informace o vytváření dotazů napříč související tabulky v souvislosti s Technologie LINQ to SQL, viz How to: Map Database Relationships.

Složené klíče

Rovnost více hodnot lze otestovat pomocí složeného klíče.Další informace naleznete v tématu Postupy: Spojení pomocí složených klíčů (Průvodce programováním v C#).Složené klíče lze také použít v group klauzule.

Příklad

Následující příklad porovnává výsledky vnitřní spojení, spojení skupiny a levé vnější spojení na stejné zdroje dat pomocí stejné odpovídající klíče.Některé zvláštní kód vkládá tyto příklady vyjasnit výsledky v zobrazení konzoly.

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.
*/

Poznámky

A join klauzule, které nejsou následovány into je přeložena Join``4 volání metody.A join klauzule, který je následován into je přeložen do GroupJoin``4 volání metody.

Viz také

Úkoly

Postupy: Provedení levých vnějších spojení (Průvodce programováním v C#)

Postupy: Provádění vnitřních spojení (Průvodce programováním v C#)

Postupy: Provádění seskupených spojení (Průvodce programováním v C#)

Postupy: Řazení výsledků klauzule join (Průvodce programováním v C#)

Postupy: Spojení pomocí složených klíčů (Průvodce programováním v C#)

Postupy: Instalace ukázkových databází

Referenční dokumentace

group – klauzule (Referenční dokumentace jazyka C#)

Koncepty

LINQ – výrazy dotazů (Průvodce programováním v C#)

Operace sjednocení

Další zdroje

Klíčová slova dotazu (Referenční dokumentace jazyka C#)