2010-03-13 16 views
10

Ayer I posted this question con respecto al uso de lambdas dentro de un método Join() para comprobar si existen 2 condiciones en 2 entidades. Recibí una respuesta sobre la pregunta, que funcionó perfectamente. Pensé que después de leer el artículo de MSDN sobre el método Enumerable.Join(), entendería exactamente lo que estaba sucediendo, pero no es así. ¿Alguien podría ayudarme a entender qué está pasando en el siguiente código (el método Join() específicamente)? Gracias por adelantado.Ayuda Entender Enumerable.Join Método

if (db.TableA.Where(a => a.UserID == currentUser) 
     .Join(db.TableB.Where(b => b.MyField == someValue), 
      o => o.someFieldID, 
      i => i.someFieldID, 
      (o,i) => o) 
     .Any()) 
{ 
    //... 
} 

Editar: Específicamente, siento curiosidad por los últimos 3 parámetros, y lo que en realidad está pasando. ¿Cómo se producen los requisitos de firma de Func (Touter, TKey), Func (TInner, TKey), etc.

Respuesta

3

Eric y Nick han brindado buenas respuestas.

También puede escribir la expresión de consulta Linq utilizando la sintaxis de consulta (vs.sintaxis del método, que está utilizando en su ejemplo):

var query = from a in db.TableA 
      join b in db.TableB on a.someFieldID equals b.someFieldID 
      where a.UserID == currentUser && b.MyField == someValue 
      select a; 

     if (query.Any()) { 
      ... 
     } 

Actualización:

usted parece estar atascado en las expresiones lambda. Es una función que pasas como una variable. Una expresión lambda es equivalente a un delegado anónimo (o método anónimo, para mí más general).

Aquí es la consulta con las expresiones lambda como delegados (sustituir EntityType con el tipo de su entidad regresaron de la Tabla A, por supuesto):

if (db.TableA.Where(delegate(EntityType a) { return a.UserID == currentUser; }) 
    .Join(db.TableB.Where(delegate(EntityType b) { return b.MyField == someValue; }), 
     delegate(EntityType o) { return o.somefieldId); }, 
     delegate(EntityType i) { return i.someFieldId); }, 
     delegate(EntityType o, EntityType i) { return o; }) 
    .Any()) 

{ // ...}

NOTA: Una expresión lambda tiene aspectos importantes que la hacen más que solo un equivalente para métodos anónimos. Recomiendo que analice otras preguntas de SO y lea en línea sobre expresiones de lambda en particular. Permiten expresar ideas muy potentes de una manera mucho más simple y elegante. Es un tema profundo, pero los conceptos básicos son fáciles de entender. Es una función que puede pasar como una variable o como un parámetro para otras funciones.

+0

Sí, de hecho lo escribí de esta manera anteriormente, luego de darme cuenta de que se podía lograr usando el método Join usando lambdas, pensé que me desafiaría a mí mismo. Todavía creo que esta manera de ser más clara, y probablemente implementaré la solución de esta manera, pero primero quiero entender completamente la otra técnica. –

+1

En su ejemplo actualizado, ¿no debería el segundo delegado (EntityType o) ser delegado (EntityType i)? –

+0

Sí, gracias Metro Smurf (no puedo creer que esas dos palabras aparezcan una tras otra, jajaja). –

2

Esta consulta está diciendo unirse TableA-TableB donde TableA.someFieldID == TableB.someFieldID y la selección de los resultados de la Tabla A y ver si hay alguna resultados en todos los

En términos de SQL piensan en ello como esto, incluso si no es LINQ to SQL ... si está familiarizado con SQL tal vez esto tiene más sentido:

Select Count(*) 
From TableA a 
    Join TableB b 
     On a.someFieldID = b.someFieldID 

Luego de comprobar si Count(*) es> 0

15

La sintaxis de unión es

FirstTable.Join(SecondTable, FirstTableKeyExtractor, SecondTableKeyExtractor, Selector) 

lo que tiene dos tablas. Usted tiene alguna clave que es común para ambas tablas. Usted proporciona dos extractores clave que saben cómo obtener la clave de cada fila en la tabla.

La lógica de unión identifica pares de filas, una de cada tabla, que tienen la misma clave.

Cada una de esas filas se ejecuta a través del selector para proyectar el resultado.

¿Eso responde su pregunta?

+0

Casi. Entiendo que el primer parámetro es una entidad (de una tabla que coincide con esas condiciones), pero tengo curiosidad de cómo funcionan los otros 3 parámetros. ¿Qué está pasando exactamente en este punto: o => o.SomeFieldID, i => i.SomeFieldID, (o, i) => o –

+0

@lush - El segundo parámetro dice qué campo de la tabla original ' re matching en ('TableA.someFieldID'), el tercer parámetro dice en qué campo de la tabla unida se está haciendo coincidir (' TableB.someFieldID'). El último parámetro dice de este conjunto de tablas recién unidas, lo que está seleccionando ... en este caso, eso es todo desde 'TableA'. En su código, puede reemplazar 'o' con' a' y 'i' con' b', lo que puede hacer que sea mucho más claro de ver. –

+0

¿Pero cómo se traduce el código "o => o.SomeFieldID" a "TableA.SomeFieldID"? ¿Qué está pasando debajo del capó? –

4

Explicación de la unión.

b = tipo de objeto de primera tabla o = tipo de objeto de primera tabla tipo i = objeto de segunda mesa

  1. db.TableB.Where(b => b.MyField == someValue) Este es el tipo de elemento de la segunda tabla
  2. o => o.someFieldID La clave de la primera tabla
  3. i => i.someFieldID La clave de la segunda tabla (que coincidirá con la clave en la primera tabla)
  4. (o,i) => o El objeto a devolver, en este caso el tipo de objeto de la primera tabla.
Cuestiones relacionadas