Compartilhar via


cláusula deunir (referência de C#)

O join cláusula é útil para associar elementos de seqüências de origem diferentes que não têm nenhum relacionamento 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 alimentos 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 desse produto quem são todos na mesma especificado região.

A join cláusula leva duas seqüências de origem como entrada. Os elementos em cada seqüência devem ser ou conter uma propriedade que pode ser comparada a uma propriedade correspondente na seqüência de. O join cláusula compara chaves especificadas igualdade usando a sintaxe especial equals palavra-chave. Todas as associações realizadas pelo join cláusula são equijoins. A forma da saída de um join cláusula depende do tipo específico de associação que você está executando. Estes são os três tipos mais comuns de associação:

  • Associação interna

  • Associação de grupo

  • Associação externa esquerda

Associação interna

O exemplo a seguir mostra um equijoin interna simple. Esta consulta produz uma simples seqüência de "nome do produto / categoria" pares. A mesma seqüência de categoria será exibido em vários elementos. Se um elemento de categories não tem correspondente products, essa categoria não aparecerão 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 How to: Realizar associações de interno (guia de programação C#).

Group Join

A join cláusula com um into é chamado de expressão de uma associação de grupo.

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 associação de grupo produz uma seqüência de resultado hierárquica, que associa elementos na seqüência de origem à esquerda com um ou mais elementos correspondentes a seqüência de origem do lado direito. Uma associação de grupo não possui nenhum equivalente em termos de relacionais; ele é essencialmente uma seqüência de matrizes de objeto.

Se nenhum elemento da seqüência correta de origem forem encontrado para corresponder a um elemento na fonte à esquerda, o join cláusula produzirá uma matriz vazia para o item. Portanto, a associação de grupo ainda basicamente é uma equijoin de interna, exceto que a seqüência de resultado é organizada em grupos.

Se você acabou de selecionar os resultados de uma associação de grupo, você pode acessar os itens, mas você não conseguir identificar a chave que eles coincidem em. Portanto, é geralmente mais úteis selecionar os resultados da associação de grupo em um novo tipo, também tem o nome da chave, como mostrado no exemplo anterior.

Você também pode, obviamente, usar o resultado de uma associação de grupo como 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 How to: Realizar associações agrupadas (guia de programação C#).

Junção externa esquerda

Em uma junção externa esquerda, todos os elementos na seqüência de origem à esquerda são retornados, mesmo se nenhum elemento correspondente na seqüência correta. Para executar uma associação externa esquerda na LINQ, use o DefaultIfEmpty método em combinação com um grupo de associação para especificar um elemento do lado direito padrão para produzir se um elemento no lado esquerdo tem nenhuma correspondência. Você pode usar null como o valor padrão de referência de qualquer tipo, ou você 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 How to: Executar esquerda junções externas (guia de programação de C#).

O operador equals

A join cláusula realiza uma equijoin. Em outras palavras, você pode apenas base correspondências em termos de igualdade de duas chaves. Outros tipos de comparações, como "maior que" ou "não iguais" não são suportados. Para tornar claro que todas as associações são equijoins, o join cláusula usa a equals palavra-chave em vez da == operador. O equals palavra-chave só pode ser usado em um join cláusula e ele difere do == operador em uma maneira importante. Com equals, a tecla esquerda consome a seqüência de origem externa, e a tecla direita consome origem interna. A fonte externa é somente no escopo no lado esquerdo da equals e a seqüência de origem interna é somente no escopo no lado direito.

Não Equijoins

Você pode executar sem equijoins, troca de associações e outras operações de associação personalizado usando vários from cláusulas para introduzir novas seqüências de forma independente em uma consulta. Para obter mais informações, consulte How to: Executar operações de associação de Personalizar (guia de programação de C#).

Ingressa no vs de coleções do objeto.tabelas relacionais

Em um LINQ expressão de consulta join operações são executadas no objeto de coleções. Coleções de objeto não podem ser "unidas" exatamente da mesma forma como duas tabelas relacionais. Em LINQ, explícita join cláusulas só são necessários quando duas seqüências de origem não estão ligadas pelo relacionamento. Quando estiver trabalhando com LINQ to SQL, a chave estrangeira tabelas são representadas no modelo de objeto como propriedades da tabela principal. Por exemplo, no banco de dados Northwind, a tabela Customer tem uma relação de chave externa 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 de ordens associadas a esse cliente. Na verdade, a associação já foi feita para você.

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

Chaves compostas

Você pode testar a igualdade de vários valores usando uma chave composta. Para obter mais informações, consulte How to: Ingressar usando composto de Chaves (guia de programação C#). As chaves compostas também podem ser usadas em um group cláusula.

Exemplo

O exemplo a seguir compara os resultados de uma associação interna, uma associação de grupo e uma associação externa esquerda mesmo fontes de dados usando as mesmas chaves correspondentes. Algum código extra é adicionado para esses exemplos para esclarecer os resultados na exibição do console.

    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 é traduzido em um Join chamada de método. A join que é seguida de cláusula into é traduzido como um GroupJoin chamada de método.

Consulte também

Tarefas

How to: Executar esquerda junções externas (guia de programação de C#)

How to: Realizar associações de interno (guia de programação C#)

How to: Realizar associações agrupadas (guia de programação C#)

How to: Ordem dos Resultados de uma cláusula de associação (guia de programação de C#)

How to: Ingressar usando composto de Chaves (guia de programação C#)

Referência

cláusula de grupo (referência de C#)

Conceitos

LINQ Expressões de consulta (guia de programação de C#)

Operações JOIN

Outros recursos

Palavras-chave de consulta (referência de C#)