¿Por qué usar LINQ Join en una simple relación uno-muchos?

He estado utilizando LINQ to SQL y Entity Framework durante algunos años y siempre he mapeado las relaciones de mi base de datos para generar las propiedades de navegación relevantes. Y siempre uso las propiedades de navegación.

¿Me estoy perdiendo de algo?

Si tengo una relación de tipo Category->Products uno-muchos, usaría

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

Regularmente veo personas haciendo uniones manuales, en todo este sitio, en proyectos en línea y en otros sitios web.

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

¿Entonces por qué? ¿Cuáles son los beneficios de usar esta syntax de unión?

Por lo general es un error.

@George tiene razón en que sus dos ejemplos son funcionalmente diferentes de una manera que no tiene nada que ver con la join versus la no join , sin embargo. Pero igual podrías escribir:

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

… que es funcionalmente idéntico (pero superior a un punto de vista de legibilidad y mantenimiento) a su ejemplo de join .

Puede resultar de portar el código anterior a linq2sql.

Sin embargo, los dos fragmentos de código no son funcionalmente iguales.

Single arrojará una excepción, mientras que join producirá una colección vacía en caso de que falte un registro.

Entonces, un código igual sin usar combinaciones sería:

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

o

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

Las uniones son probablemente más comunes para las personas que provienen de la mentalidad relacional en lugar de la orientada a objetos. Si piensa en el espacio de su problema desde una perspectiva orientada a objetos, es mucho más natural trabajar con relaciones donde puede salpicar a través de la navegación: Employee.Customers.Orders.OrderItems.OrderItem que tratar con un montón de combinaciones. El documento original original ADO.vNext hizo un buen trabajo al discutir las ventajas de usar el modelo y las asociaciones en lugar de unirse para tratar con sus modelos conceptuales. Lamentablemente, no puedo encontrar ese documento en este punto.

Para mí, las combinaciones se usan mejor cuando no tienes asociaciones naturales entre entidades. Por ejemplo, si está intentando unir elementos con claves no naturales (es decir, uniéndose a Customer.State y Shipping.State ), debe usar la syntax de unión (o SelectMany ) en lugar de crear asociaciones entre sus entidades en este caso.

Una cosa a tener en cuenta es que la syntax de unión y el uso de asociaciones pueden causar diferencias en el tipo de uniones generadas por el proveedor. Normalmente, una combinación se traduce en una combinación interna y excluye elementos en los que no hay coincidencia en ambos lados de la combinación. Para realizar una combinación externa (izquierda), usa la extensión DefaultIfEmpty .

Navegar a través de asociaciones en una relación 1-0 .. * por otro lado normalmente se traduce en uniones externas derechas porque la colección hija podría estar legítimamente vacía y usted querría incluir al padre aunque el niño no existiera. ¡Utilizaría !Any() para atrapar casos si no hubiera registros secundarios.