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 <=>.

È stato utile?

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?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top