Como: Executar operações de unir personalizada (guia de programação translation from VPE for Csharp)

Este exemplo mostra como executar as operações de unir que não são possíveis com o join cláusula. Uma expressão de consulta, o join cláusula está limitada e otimizado para, o tipo de equiunirs, que são de longe mais comuns de unir operação. Ao realizar um junção por igualdade, provavelmente sempre irá obter o melhor desempenho usando o join cláusula.

No entanto, há alguns casos onde o join a cláusula não pode ser usada:

  • Quando a unir é vinculada em uma expressão de desigualdade (um não-junção por igualdade).

  • Quando a unir é vinculada em mais de uma expressão de igualdade ou operador de desigualdade.

  • Quando você tem que introduzir uma variável de intervalo temporário para a sequência direita (interno) antes da operação de ingresso.

Para realizar associações que não são equijoins, você pode usar vários from cláusulas de apresentar cada fonte de dados independentemente. Em seguida, você aplicar uma expressão de predicado em um where cláusula para a variável de intervalo para cada fonte. A expressão também pode fazer com que o formulário de uma telefonar de método.

Observação:

Não confunda esse tipo de operação de unir personalizada com o uso de vários from cláusulas de acessar coleções internas. Para obter mais informações, consulte cláusula de unir (translation from VPE for Csharp Reference).

Exemplo

O primeiro método no exemplo a seguir mostra uma simples unir cruzada.Junções cruzadas devem ser usadas com cuidado porque eles podem produzir conjuntos de resultados muito grande.No entanto, elas podem ser úteis em alguns cenários para a criação de seqüências de fonte que consultas adicionais que são executadas.

O segundo método produz uma sequência de todos os produtos cujo ID da categoria é listado na lista de categorias no lado esquerdo.Observe o uso do let cláusula e o Contains método para criar uma matriz temporária. Também é possível criar a matriz antes da consulta e eliminar o primeiro from cláusula.

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

No exemplo a seguir, a consulta deve associar-se duas seqüências com base na correspondência de chaves que, no caso da sequência interna (lado direito) não podem ser obtidas antes para a cláusula de unir.Se esta unir foram executada com um join cláusula e, em seguida, o método split terão que ser chamada para cada elemento. O uso de vários from cláusulas permite que a consulta evitar a sobrecarga de telefonar do método repetidas. No entanto, desde que a unir é otimizada, nesse caso específico ainda será mais rápido do que usar múltiplos de cláusulas.Os resultados irão variar dependendo principalmente caro como a telefonar do método.

class MergeTwoCSVFiles : StudentClass
{
    static void Main()
    {
        string[] names = System.IO.File.ReadAllLines(@"../../../names.csv");
        string[] scores = System.IO.File.ReadAllLines(@"../../../scores.csv");

        // Merge the data sources using a named type
        // var could be used instead of an explicit type
        IEnumerable<Student> queryNamesScores =
            from name in names
            let x = name.Split(',')
            from score in scores
            let s = score.Split(',')
            where x[2] == s[0]
            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();
    }
}
/* Output: 
    The average score of Adams Terry is 85.25.
    The average score of Fakhouri Fadi is 92.25.
    The average score of Feng Hanying is 88.
    The average score of Garcia Cesar is 88.25.
    The average score of Garcia Debra is 67.
    The average score of Garcia Hugo is 85.75.
    The average score of Mortensen Sven is 84.5.
    The average score of O'Donnell Claire is 72.25.
    The average score of Omelchenko Svetlana is 82.5.
    The average score of Tucker Lance is 81.75.
    The average score of Tucker Michael is 92.
    The average score of Zabokritski Eugene is 83.
 */

Este exemplo também pode ser encontrado no artigo Como: Preencher coleções de objetos de Múltiplo fontes (LINQ). Para compilar e executar esse exemplo, siga as instruções no artigo.

Compilando o código

  • Criar um Visual Studio projeto que se destina a .NET estrutura versão 3.5. Por padrão, o projeto tem uma referência a sistema.Core.dll e um using diretiva para o namespace sistema.LINQ.

  • Copie o código em seu projeto.

  • Pressione F5 para compilar e executar o programa.

  • Pressione qualquer tecla para sair da janela do console.

Consulte também

Tarefas

Como: Ordenar os resultados de uma cláusula unir (guia de programação translation from VPE for Csharp)

Conceitos

Expressões de consulta do LINQ (guia de programação translation from VPE for Csharp)

Junção operações

Referência

cláusula de unir (translation from VPE for Csharp Reference)