Por que usar o LINQ Participe de um relacionamento simples e único?

Eu tenho usado o LINQ to SQL e o Entity Framework por alguns anos e sempre mapeei meus relacionamentos de database para gerar as propriedades de navegação relevantes. E eu sempre uso as propriedades de navegação.

Estou esquecendo de algo?

Se eu tiver um relacionamento do tipo Category->Products , eu usaria

 var redProducts = context.Category.Single(c => c.Name = "red").Products; 

Eu regularmente vejo pessoas fazendo junções manuais, em todo este site, em projetos on-line e vários outros sites.

 var employer = from category in context.Categories join product in context.Products on category.CategoryId equals product.CategoryId where category.Name == "red" select product; 

Então por que? Quais são os benefícios de usar essa syntax de associação?

Geralmente é um erro.

@George está correto em dizer que seus dois exemplos são funcionalmente diferentes de uma forma que não tem nada a ver com join vs non- join , no entanto. Mas você poderia facilmente escrever:

 var redProducts = context.Category .Where(c => c.Name == "red") .SelectMany(c => c.Products); 

… que é funcionalmente idêntico (mas superior de um POV de legibilidade e facilidade de manutenção) ao seu exemplo de join .

Isso pode resultar de portar o código antigo para o linq2sql.

No entanto, os dois trechos de código não são funcionalmente iguais.

Single lançará exceção, enquanto join produz uma coleção vazia em caso de registro ausente.

Então, um código igual sem usar joins seria:

 from c in context.Categories where c.Name == "red" from p in c.Products select p; 

ou

 context.Categories.Where(c=>c.Name == "red").SelectMany(c=>c.Products); 

Joins são provavelmente mais comuns para pessoas que vêm da mentalidade Relacional, em vez da orientada a objects. Se você pensar sobre o espaço do seu problema a partir de uma perspectiva orientada a objects, é muito mais natural trabalhar com relacionamentos nos quais você possa navegar através da navegação: Employee.Customers.Orders.OrderItems.OrderItem do que lidar com um monte de junções. O white paper original do ADO.vNext fez um bom trabalho ao discutir as vantagens de usar o modelo e as associações em vez de junções para lidar com seus modelos conceituais. Infelizmente, não consigo encontrar esse documento neste momento.

Para mim, as junções são mais usadas quando você não tem associações naturais entre entidades. Por exemplo, se você estiver tentando unir itens em chaves não naturais (ou seja, ingressar no Customer.State e Shipping.State ), use a syntax de associação (ou SelectMany ) em vez de criar associações entre suas entidades nesse caso.

Uma coisa a ter em conta é que a syntax de junit e o uso de associações podem causar diferenças no tipo de junções geradas pelo provedor. Normalmente, uma associação se traduz em uma junit interna e exclui itens em que não há correspondência em ambos os lados da junit. Para executar uma junit externa (esquerda), use a extensão DefaultIfEmpty .

Navegar pelas associações em um relacionamento 1-0 .. *, por outro lado, normalmente se traduz em associações do Right Outer porque a coleção filho pode estar legitimamente vazia e você deseja include o pai mesmo que o filho não exista. Você usaria !Any() para interceptar os casos em que não há registros de filhos.