Unión externa izquierda y existe en Linq a SQL C # .NET 3.5
-
03-07-2019 - |
Pregunta
Estoy atascado en traducir una combinación externa izquierda de LINQToSQL que devuelve filas primarias únicas.
Tengo 2 tablas (Project, Project_Notes, y es una relación de 1-muchos vinculada por Project_ID). Estoy haciendo una búsqueda de palabras clave en varias columnas en la tabla 2 y solo quiero devolver los proyectos únicos si una columna en Project_Notes contiene una palabra clave. Tengo esta secuencia linqtoSQl funcionando pero parece que devuelve varias filas del Proyecto. ¿Quizás hacer un Exist
de alguna manera en LINQ? ¿O tal vez un grupo de algún tipo?
Aquí está el LINQToSQL:
query = from p in query
join n in notes on p.PROJECT_ID equals n.PROJECT_ID into projectnotes
from n in notes.DefaultIfEmpty()
where n.NOTES.Contains(cwForm.search1Form)
select p;
aquí está el SQL que produjo del generador de perfiles
exec sp_executesql N'SELECT [t2]. [Título], [t2]. [Estado], [t2]. [PROYECTO_ID], [t2]. [PROVIDER_ID], [t2]. [CATEGORY_ID], [t2]. [Ciudad], [t2]. [UploadedDate], [t2]. [EnviadoDate], [t2]. [Project_Type] FROM (SELECT ROW_NUMBER () OVER (ORDER BY [t0]. [UploadedDate]) AS [ROW_NUMBER], [t0]. [Title], [t0]. [State], [t0]. [PROJECT_ID], [t0]. [PROVIDER_ID], [t0]. [CATEGORY_ID], [t0]. [Ciudad], [t0]. [UploadedDate], [t0]. [SubmitDate], [t0]. [Project_Type] FROM [dbo]. [PROJECTS] AS [t0] IZQUIERDA EXTERIOR UNIRSE [dbo]. [PROYECTO_NOTAS] COMO [t1] EN 1 = 1 DONDE ([t1]. [NOTAS] ME GUSTA @ p0) Y ([t0] .SubmittedDate] > = @ p1) AND ([t0]. [SubmitDate] < @ p2) AND ([t0]. [PROVIDER_ID] = @ p3) Y ([t0]. [CATEGORY_ID] ES NULO)) COMO [t2] DONDE [t2]. [ROW_NUMBER] ENTRE @ p4 + 1 Y @ p4 + @ p5 ORDER BY [t2]. [ROW_NUMBER] ', N' @ p0 varchar (9), @ p1 datetime, @ p2 datetime, @ p3 int, @ p4 int, @ p5 int ', @ p0 ='% chicago% ', @ p1 =' '2000-09-02 00: 00: 00: 000' ', @ p2 =' '2009-03-02 00: 00: 00: 000 '', @ p3 = 1000, @ p4 = 373620, @ p5 = 20
Esta consulta devuelve todos los mutiples de la relación 1-muchos en los resultados. Encontré cómo hacer un Exists
en LINQ desde aquí. http: / /www.linq-to-sql.com/linq-to-sql/t-sql-to-linq-upgrade/linq-exists/
Aquí está el LINQToSQL usando databind()
:
query = from p in query
where (from n in notes
where n.NOTES.Contains(cwForm.search1Form)
select n.PROJECT_ID).Contains(p.PROJECT_ID)
select p;
La instrucción SQL generada:
exec sp_executesql N'SELECT COUNT (*) AS [value] FROM [dbo]. [PROJECTS] AS [t0] WHERE (EXISTE (SELECCIONE NULL COMO [VACÍO] DE [dbo]. [PROYECTO_NOTAS] COMO [t1] DONDE ([t1] .PROJECT_ID] = ([t0]. [PROJECT_ID])) AND ([t1]. [NOTES] LIKE @ p0))) AND ([t0]. [EnviadoDate] > = @ p1) AND ([t0]. [EnviadoDate] < @ p2) AND ([t0]. [PROVIDER_ID] = @ p3) AND ([t0]. [CATEGORY_ID] IS NULL) ', N' @ p0 varchar (9), @ p1 datetime, @ p2 datetime, @ p3 int ', @ p0 ='% chicago% ', @ p1 =' '2000-09-02 00: 00: 00: 000' ', @ p2 =' '2009-03-02 00: 00: 00: 000 '', @ p3 = 1000
Obtuve un tiempo de espera de SQL de <=> al usar <=>.
Solución
parece estar devolviendo múltiples filas del Proyecto
Sí, así es como funciona join. Si un proyecto tiene 5 notas coincidentes, se mostrará 5 veces.
¿Qué pasa si el problema es - " Únete " es el idioma equivocado!
Desea filtrar los proyectos a aquellos cuyas notas contienen cierto texto:
var query = db.Project
.Where(p => p.Notes.Any(n => n.NoteField.Contains(searchString)));
Otros consejos
Tendrá que usar el método de extensión DefaultIfEmpty. Ya hay algunas preguntas sobre SO que muestran cómo hacer esto. Aquí hay un buen ejemplo:
¿Cómo puedo realizar un Unir, Agregar y Agrupar anidados en LINQ?