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

The join cláusula é útil para associar elementos de fonte diferentes seqüências que não têm nenhum Relação direto no modelo de objeto. O único requisito é que os elementos em cada fonte compartilham algum valor que pode ser comparado a igualdade.Por exemplo, um distribuidor de comida pode ter uma lista de fornecedores de um determinado produto e uma lista de compradores.A join cláusula pode ser usada, por exemplo, para criar uma lista de fornecedores e compradores do produto que são todos na mesma especificado região.

A join cláusula utiliza duas seqüências de fonte sistema autônomo entrada. Os elementos em cada sequência devem ser ou conter uma propriedade que pode ser comparada a uma propriedade correspondente na Outros sequência.The join cláusula compara chaves especificadas igualdade usando o especiais equals palavra-chave. Todas as associações executadas pelo join cláusula são equijoins. A forma da saída de um join cláusula depende do tipo específico de unir que você está executando. Três tipos de unir mais comuns são:

  • Interna unir

  • unir de agrupar

  • junção externa esquerda

Interna unir

O exemplo a seguir mostra um junção por igualdade interna simples.Esta consulta produz uma simples sequência de “ nome do produto / categoria ” pares.A mesma seqüência de categoria aparecerão na vários elementos.Se um elemento de categories não tem nenhuma correspondência products, essa categoria não aparecerá nos resultados.

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

Para obter mais informações, consulte Como: Executar associações interna (guia de programação translation from VPE for Csharp).

Group Join

A join cláusula com um into expressão é denominado uma unir de agrupar.

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

Uma unir de agrupar produz uma sequência de resultado hierárquica, que associa elementos na sequência de fonte à esquerda com um ou mais elementos correspondentes da sequência de fonte do lado direito.Uma unir de agrupar não possui nenhum equivalente em termos relacionais; ele é essencialmente uma sequência de matrizes de objeto.

Não se for encontrado nenhum elemento da sequência de fonte correta para coincidir com um elemento de fonte à esquerda, a join cláusula resultará em uma matriz vazia para o item. Portanto, a unir de agrupar é ainda basicamente um junção por igualdade interna, exceto pelo fato de que a sequência de resultado é organizada em grupos.

Se você selecionar apenas os resultados de uma unir de agrupar, você pode acessar os itens, mas você não pode identificar a chave que eles coincidem em.Portanto, é geralmente mais úteis selecionar sistema autônomo resultados da unir de agrupar para um novo tipo também tem o nome de chave, sistema autônomo mostrado no exemplo anterior.

Além disso, você pode usar claro, o resultado de uma unir de agrupar sistema autônomo o gerador de outra subconsulta:

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;    

Para obter mais informações, consulte Como: Executar associações agrupadas (guia de programação translation from VPE for Csharp).

Junção externa esquerda

Em um junção externa esquerda, todos os elementos na sequência de fonte à esquerda são retornados, mesmo se nenhum elemento correspondente no sequência correta.Para executar uma unir externa esquerda em LINQ, use o DefaultIfEmpty método em combinação com uma unir de agrupar para especificar um elemento do lado direito padrão para produzir se um elemento esquerda não tem nenhuma correspondência. Você pode usar null sistema autônomo o valor padrão de referência de qualquer tipo, ou pode especificar um tipo definido pelo usuário padrão. No exemplo a seguir, um tipo definido pelo usuário padrão é mostrado:

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

Para obter mais informações, consulte Como: Executar associações externas (guia de programação translation from VPE for Csharp) à esquerda.

O operador equals

A join cláusula executa um junção por igualdade. Em outras palavras, você pode apenas base correspondências em igualdade de duas chaves.Não há suporte para outros tipos de comparações, sistema autônomo "maior que" ou "não igual a".Para tornar claro que todas as associações são equijoins, a join cláusula usa o equals palavra-chave em vez da == operador. The equals palavra-chave só pode ser usado em um join cláusula e ele difere do == operador de uma maneira importante. Com equals, a tecla esquerda consome a sequência de origem externa e a chave correta consome a fonte interna. A fonte externa está somente no escopo no lado esquerdo da equals e a sequência de origem interna somente no escopo no lado direito.

Não Equijoins

Você pode executar sem equijoins, entre associações, e Outros as operações de unir personalizado, usando vários from cláusulas de introduzir novas seqüências independentemente em uma consulta. Para obter mais informações, consulte Como: Executar operações de unir personalizada (guia de programação translation from VPE for Csharp).

Ingressa no objeto coleções vs.tabelas relacionais

In a LINQ expressão de consulta, as operações são executadas em coleções de objeto de unir. Coleções do objeto não podem ser "associadas" exatamente da mesma forma sistema autônomo duas tabelas relacionais.In LINQ, explícita join cláusulas só são necessários quando duas seqüências de fonte não estão ligadas por qualquer relação. Ao trabalhar com LINQ to SQL, tabelas de chaves externas são representadas no modelo de objeto sistema autônomo propriedades da tabela primária. Por exemplo, no banco de dados Northwind, a tabela cliente tem uma relação de chave estrangeira com a tabela Pedidos.Quando você mapeia as tabelas ao modelo de objeto, a classe Customer tem uma propriedade de pedidos que contém a coleção Orders associados a esse cliente.Na verdade, a unir já foi realizada para você.

Para obter mais informações sobre consultando entre tabelas relacionadas no contexto de LINQ to SQL, consulte How to: Map Database Relationships (LINQ to SQL).

Chaves compostas

Você pode testar igualdade de vários valores usando uma chave composta.Para obter mais informações, consulte Como: unir usando chaves compostas (guia de programação translation from VPE for Csharp).As chaves compostas também podem ser usadas em um group cláusula.

Exemplo

O exemplo a seguir compara o resultados de uma junção interna, uma unir de agrupar e uma unir externa esquerda em fontes de dados mesmo usando as teclas mesmas correspondentes.Alguns códigos extra é adicionado a esses exemplos para esclarecer a exibição do console, o resultado.

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

Comentários

A join cláusula que não é seguida por into é convertida em uma Join telefonar de método. A join cláusula for seguida de into é convertida para um GroupJoin telefonar de método.

Consulte também

Tarefas

Como: Executar associações externas (guia de programação translation from VPE for Csharp) à esquerda

Como: Executar associações interna (guia de programação translation from VPE for Csharp)

Como: Executar associações agrupadas (guia de programação translation from VPE for Csharp)

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

Como: unir usando chaves compostas (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 agrupar (translation from VPE for Csharp Reference)

Outros recursos

Palavras-chave de consulta (translation from VPE for Csharp Reference)