Sinistra join esterno ed esiste in Linq a SQL C # .NET 3.5
-
03-07-2019 - |
Domanda
Sono bloccato a tradurre un join esterno sinistro da LINQToSQL che restituisce righe padre univoche.
Ho 2 tabelle (Project, Project_Notes, ed è una relazione 1-molti collegata da Project_ID). Sto eseguendo una ricerca per parola chiave su più colonne nella tabella 2 e desidero restituire i progetti univoci solo se una colonna in Project_Notes contiene una parola chiave. Ho questa sequenza linqtoSQl in corso ma sembra che stia restituendo più righe di progetto. Forse fare un Exist
in qualche modo in LINQ? O forse un groupby di qualche tipo?
Ecco 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;
ecco l'SQL prodotto dal profiler
exec sp_executesql N'SELECT [t2]. [Title], [t2]. [State], [t2]. [PROJECT_ID], [t2]. [PROVIDER_ID], [t2]. [CATEGORY_ID], [t2]. [City], [t2]. [UploadedDate], [t2]. [SubmittedDate], [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]. [City], [t0]. [UploadedDate], [t0]. [SubmittedDate], [t0]. [Project_Type] FROM [dbo]. [PROJECTS] AS [t0] LEFT OUTER JOIN [dbo]. [PROJECT_NOTES] AS [t1] ON 1 = 1 DOVE ([t1]. [NOTE] COME @ p0) E ([t0] .SubmittedDate] > = @ p1) AND ([t0]. [SubmittedDate] < @ p2) AND ([t0]. [PROVIDER_ID] = @ p3) AND ([t0]. [CATEGORY_ID] IS NULL)) AS [t2] DOVE [t2]. [ROW_NUMBER] TRA @ p4 + 1 AND @ 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 = 373.620, @ p5 = 20
Questa query restituisce tutti i multipli della relazione 1-many nei risultati. Ho trovato come fare un Exists
in LINQ da qui. http: / /www.linq-to-sql.com/linq-to-sql/t-sql-to-linq-upgrade/linq-exists/
Ecco 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;
L'istruzione SQL generata:
exec sp_executesql N'SELECT COUNT (*) AS [value] FROM [dbo]. [PROJECTS] AS [t0] DOVE (ESISTE (SELEZIONA NULL AS [EMPTY] DA [dbo]. [PROJECT_NOTES] AS [t1] DOVE ([t1] .PROJECT_ID] = ([t0]. [PROJECT_ID])) AND ([t1]. [NOTE] COME @ p0))) E ([t0]. [SubmittedDate] > = @ p1) AND ([t0]. [SubmittedDate] < @ 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
Ottengo un timeout SQL da <=> dall'uso di <=>.
Soluzione
sembra che stia restituendo più righe di progetto
Sì, è così che funziona join. Se un progetto ha 5 note corrispondenti, viene visualizzato 5 volte.
Che cosa succede se il problema è - " Join " è il linguaggio sbagliato!
Desideri filtrare i progetti su quelli le cui note contengono un determinato testo:
var query = db.Project
.Where(p => p.Notes.Any(n => n.NoteField.Contains(searchString)));
Altri suggerimenti
Dovrai utilizzare il metodo di estensione DefaultIfEmpty. Ci sono già alcune domande su SO che mostrano come farlo. Ecco un buon esempio:
Come posso eseguire un annidato Partecipare, aggiungere e raggruppare in LINQ?