Sdílet prostřednictvím


Postupy: Provádění vlastních operací spojování (Průvodce programováním v C#)

Tento příklad ukazuje, jak provádět operace spojení, které není možné s join klauzule.Ve výrazu dotazu join klauzule je omezena na a optimalizované pro equijoins, které jsou mnohem nejběžnější typ operace join.Po provedení porovnávání pomocí pravděpodobně vždy získáte nejlepší výkon join klauzule.

Však join klauzuli by nelze použít v následujících případech:

  • Při spojení záleží na výraz nerovnost (non porovnávání).

  • Při spojení záleží na více než jeden výraz rovnosti nebo nerovnost.

  • Když máte zavést dočasné rozsah proměnné pro posloupnost (vnitřní) na pravé straně před operací spojení.

Chcete-li provést spojení, které nejsou equijoins, můžete použít více from klauzule zavést jednotlivé zdroje dat nezávisle.Pak použít predikátu výraz v where klauzule rozsahu proměnné pro každý zdroj.Výraz může také mít formu volání metody.

[!POZNÁMKA]

Nepleťte si tento druh operace vlastní spojení s použitím více from klauzule přístup vnitřní kolekce.Další informace naleznete v tématu join – klauzule (Referenční dokumentace jazyka C#).

Příklad

První metoda následující příklad ukazuje jednoduchý křížové spojení.Křížové spojení musí používat opatrně, protože vytvářejí velmi velké výsledné sady.Že však může být užitečné v některých scénářích pro vytváření zdroje sekvencí, proti kterým jsou spuštěny další dotazy.

Druhá metoda vytvoří posloupnost všechny produkty, jejichž ID kategorií je uveden v seznamu kategorií na levé straně.Poznámka: použití let klauzule a Contains metody pro vytvoření dočasné pole.Také je možné vytvořit pole před dotaz a odstranit první from klauzule.

class CustomJoins
     {

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

         // Specify the second data source.
         List<Product> products = new List<Product>()
{
   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},
   new Product{Name="Ice Cream", CategoryID=007},
   new Product{Name="Mackerel", CategoryID=012},
 };
         #endregion

         static void Main()
         {
             CustomJoins app = new CustomJoins();
             app.CrossJoin();
             app.NonEquijoin();

             Console.WriteLine("Press any key to exit.");
             Console.ReadKey();
         }

         void CrossJoin()
         {
             var crossJoinQuery =
                 from c in categories
                 from p in products
                 select new { c.ID, p.Name };

             Console.WriteLine("Cross Join Query:");
             foreach (var v in crossJoinQuery)
             {
                 Console.WriteLine("{0,-5}{1}", v.ID, v.Name);
             }
         }

         void NonEquijoin()
         {
             var nonEquijoinQuery =
                 from p in products
                 let catIds = from c in categories
                              select c.ID
                 where catIds.Contains(p.CategoryID) == true 
                 select new { Product = p.Name, CategoryID = p.CategoryID };

             Console.WriteLine("Non-equijoin query:");
             foreach (var v in nonEquijoinQuery)
             {
                 Console.WriteLine("{0,-5}{1}", v.CategoryID, v.Product);
             }
         }
     }
     /* Output:
 Cross Join Query:
 1    Tea
 1    Mustard
 1    Pickles
 1    Carrots
 1    Bok Choy
 1    Peaches
 1    Melons
 1    Ice Cream
 1    Mackerel
 2    Tea
 2    Mustard
 2    Pickles
 2    Carrots
 2    Bok Choy
 2    Peaches
 2    Melons
 2    Ice Cream
 2    Mackerel
 3    Tea
 3    Mustard
 3    Pickles
 3    Carrots
 3    Bok Choy
 3    Peaches
 3    Melons
 3    Ice Cream
 3    Mackerel
 Non-equijoin query:
 1    Tea
 2    Mustard
 2    Pickles
 3    Carrots
 3    Bok Choy
 Press any key to exit.
      */

V následujícím příkladu dotazu musí spojit dvě sekvence na základě odpovídající klíče, které z posloupnosti vnitřní (vpravo), nemůže být získané před klauzule join, sám.Pokud je toto spojení, které byly provedeny s join klauzule, pak bude Split metoda by musel být volán pro každý prvek.Použití více from umožňuje klauzule dotazu by se metoda opakovaných volání.Však od join je optimalizována, v tomto případě může být rychlejší než použití více from klauzule.Výsledky se budou lišit podle toho, jak drahého volání metody je především.

class MergeTwoCSVFiles
{
    static void Main()
    {
        // See section Compiling the Code for information about the data files. 
        string[] names = System.IO.File.ReadAllLines(@"../../../names.csv");
        string[] scores = System.IO.File.ReadAllLines(@"../../../scores.csv");

        // Merge the data sources using a named type. 
        // You could use var instead of an explicit type for the query.
        IEnumerable<Student> queryNamesScores =
            // Split each line in the data files into an array of strings. 
            from name in names
            let x = name.Split(',')
            from score in scores
            let s = score.Split(',')
            // Look for matching IDs from the two data files. 
            where x[2] == s[0]
            // If the IDs match, build a Student object. 
            select new Student()
            {
                FirstName = x[0],
                LastName = x[1],
                ID = Convert.ToInt32(x[2]),
                ExamScores = (from scoreAsText in s.Skip(1)
                              select Convert.ToInt32(scoreAsText)).
                              ToList()
            };

        // Optional. Store the newly created student objects in memory 
        // for faster access in future queries
        List<Student> students = queryNamesScores.ToList();

        foreach (var student in students)
        {
            Console.WriteLine("The average score of {0} {1} is {2}.",
                student.FirstName, student.LastName, student.ExamScores.Average());
        }

        //Keep console window open in debug mode
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int ID { get; set; }
    public List<int> ExamScores { get; set; }
}

/* Output: 
    The average score of Omelchenko Svetlana is 82.5.
    The average score of O'Donnell Claire is 72.25.
    The average score of Mortensen Sven is 84.5.
    The average score of Garcia Cesar is 88.25.
    The average score of Garcia Debra is 67.
    The average score of Fakhouri Fadi is 92.25.
    The average score of Feng Hanying is 88.
    The average score of Garcia Hugo is 85.75.
    The average score of Tucker Lance is 81.75.
    The average score of Adams Terry is 85.25.
    The average score of Zabokritski Eugene is 83.
    The average score of Tucker Michael is 92.
 */

Probíhá kompilace kódu

  • Vytvoření Visual Studio projekt aplikace konzoly, který se zaměřuje na .NET Framework 3.5 nebo vyšší.Ve výchozím nastavení projektu odkazuje na System.Core.dll a using směrnice pro obor názvů System.Linq.

  • Nahradit Program třídu s kódem v předchozím příkladu.

  • Postupujte podle pokynů v Postupy: Spojení obsahu z nepodobných souborů (LINQ) nastavit datové soubory, scores.csv a names.csv.

  • Stisknutím klávesy F5 sestavit a spustit program.

  • Stisknutím libovolné klávesy uzavřete okno konzoly.

Viz také

Úkoly

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

Referenční dokumentace

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

Koncepty

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

Operace sjednocení