LINQ to SQL: varias combinaciones en varias columnas. es posible?

Dado:

Una tabla llamada TABLE_1 con las siguientes columnas:

  • ID
  • ColumnA
  • ColumnB
  • ColumnC

Tengo una consulta SQL donde TABLE_1 une a sí misma dos veces a partir de ColumnA , ColumnB , ColumnC . La consulta puede ser algo como esto:

 Select t1.ID, t2.ID, t3.ID From TABLE_1 t1 Left Join TABLE_1 t2 On t1.ColumnA = t2.ColumnA And t1.ColumnB = t2.ColumnB And t1.ColumnC = t2.ColumnC Left Join TABLE_1 t3 On t2.ColumnA = t3.ColumnA And t2.ColumnB = t3.ColumnB And t2.ColumnC = t3.ColumnC ... and query continues on etc. 

Problema:

Necesito que Query se reescriba en LINQ. He intentado darle una puñalada:

 var query = from t1 in myTABLE1List // List join t2 in myTABLE1List on t1.ColumnA equals t2.ColumnA && t1.ColumnB equals t2.ColumnA // ... and at this point intellisense is making it very obvious // I am doing something wrong :(

¿Cómo escribo mi consulta en LINQ? ¿Qué estoy haciendo mal?

Unirse en varias columnas en Linq a SQL es un poco diferente.

 var query = from t1 in myTABLE1List // List join t2 in myTABLE1List on new { t1.ColumnA, t1.ColumnB } equals new { t2.ColumnA, t2.ColumnB } ... 

Debe aprovechar los tipos anónimos y componer un tipo para las columnas múltiples con las que desea comparar.

Esto parece confuso al principio, pero una vez que se familiarice con la forma en que se compone el SQL a partir de las expresiones tendrá mucho más sentido, bajo las coberturas esto generará el tipo de unión que está buscando.

EDITAR Agregar ejemplo para la segunda unión basada en el comentario.

 var query = from t1 in myTABLE1List // List join t2 in myTABLE1List on new { A = t1.ColumnA, B = t1.ColumnB } equals new { A = t2.ColumnA, B = t2.ColumnB } join t3 in myTABLE1List on new { A = t2.ColumnA, B = t2.ColumnB } equals new { A = t3.ColumnA, B = t3.ColumnB } ... 

En LINQ2SQL, rara vez necesita unirse explícitamente cuando usa uniones internas.

Si tiene relaciones de claves externas adecuadas en su base de datos, obtendrá automáticamente una relación en el diseñador de LINQ (si no puede crear una relación manualmente en el diseñador, aunque realmente debería tener relaciones adecuadas en su base de datos)

relación padre-hijo

Luego puede acceder a las tablas relacionadas con la “notación de puntos”

 var q = from child in context.Childs where child.Parent.col2 == 4 select new { childCol1 = child.col1, parentCol1 = child.Parent.col1, }; 

generará la consulta

 SELECT [t0].[col1] AS [childCol1], [t1].[col1] AS [parentCol1] FROM [dbo].[Child] AS [t0] INNER JOIN [dbo].[Parent] AS [t1] ON ([t1].[col1] = [t0].[col1]) AND ([t1].[col2] = [t0].[col2]) WHERE [t1].[col2] = @p0 -- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [4] -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1 

En mi opinión, esto es mucho más legible y te permite concentrarte en tus condiciones especiales y no en la mecánica real de la unión.

Editar
Por supuesto, esto solo es aplicable cuando quiere unirse a la línea con nuestro modelo de base de datos. Si desea unirse a “fuera del modelo”, debe recurrir a uniones manuales como en la respuesta de Quintin Robinson.

Title_Authors es una búsqueda de dos cosas, únete a los resultados del proyecto y sigue encadenando

  DataClasses1DataContext db = new DataClasses1DataContext(); var queryresults = from a in db.Authors join ba in db.Title_Authors on a.Au_ID equals ba.Au_ID into idAuthor from c in idAuthor join t in db.Titles on c.ISBN equals t.ISBN select new { Author = a.Author1,Title= t.Title1 }; foreach (var item in queryresults) { MessageBox.Show(item.Author); MessageBox.Show(item.Title); return; } 

U también puede usar:

 var query = from t1 in myTABLE1List join t2 in myTABLE1List on new { ColA=t1.ColumnA, ColB=t1.ColumnB } equals new { ColA=t2.ColumnA, ColB=t2.ColumnB } join t3 in myTABLE1List on new {ColC=t2.ColumnA, ColD=t2.ColumnB } equals new { ColC=t3.ColumnA, ColD=t3.ColumnB } 

Me gustaría dar otro ejemplo en el que se usan múltiples (3) uniones.

  DataClasses1DataContext ctx = new DataClasses1DataContext(); var Owners = ctx.OwnerMasters; var Category = ctx.CategoryMasters; var Status = ctx.StatusMasters; var Tasks = ctx.TaskMasters; var xyz = from t in Tasks join c in Category on t.TaskCategory equals c.CategoryID join s in Status on t.TaskStatus equals s.StatusID join o in Owners on t.TaskOwner equals o.OwnerID select new { t.TaskID, t.TaskShortDescription, c.CategoryName, s.StatusName, o.OwnerName }; 

También puede unirse si el número de columnas no es el mismo en ambas tablas y puede asignar el valor estático a la columna de la tabla

 from t1 in Table1 join t2 in Table2 on new {X = t1.Column1, Y = 0 } on new {X = t2.Column1, Y = t2.Column2 } select new {t1, t2} 

En mi opinión, esta es la forma más simple de unir dos tablas con múltiples campos:

 from a in Table1 join b in Table2 on (a.Field1.ToString() + "&" + a.Field2.ToString()) equals (b.Field1.ToString() + "&" + b.Field2.ToString()) select a 

Puedes escribir tu consulta así.

 var query = from t1 in myTABLE1List // List join t2 in myTABLE1List on t1.ColumnA equals t2.ColumnA and t1.ColumnB equals t2.ColumnA 

Si desea comparar su columna con varias columnas.