Left Outer Join e existe em Linq To SQL C # .NET 3.5
-
03-07-2019 - |
Pergunta
Eu estou preso em traduzir uma junção externa esquerda de LINQToSQL que retorna linhas pai únicas.
Eu tenho 2 tabelas (Projeto, Project_Notes, e é um relacionamento 1-muitos ligado por project_id). Estou fazendo uma pesquisa palavra-chave em várias colunas na mesa de 2 e eu só quero retornar os projectos únicos se uma coluna no Project_Notes contém uma palavra-chave. Eu tenho essa sequência LinqToSQL indo mas parece estar voltando várias linhas de projeto. Talvez fazer um Exist
de alguma forma em LINQ? Ou talvez um groupby de algum tipo?
Aqui está o 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;
aqui está o SQL-lo produzido a partir de profiler
exec sp_executesql N'SELECT [t2]. [Título], [t2]. [Estado], [t2]. [PROJECT_ID], [T2]. [PROVIDER_ID], [t2]. [CATEGORY_ID], [t2]. [City], [t2]. [UploadedDate], [T2]. [SubmittedDate], [t2]. [Project_Type] DA (SELECCIONAR ROW_NUMBER () SOBRE O (POR ORDEM [T0]. [UploadedDate]) AS [ROW_NUMBER], [t0]. [Título], [t0]. [Estado], [t0]. [PROJECT_ID], [T0]. [PROVIDER_ID], [t0]. [CATEGORY_ID], [t0]. [City], [t0]. [UploadedDate], [T0]. [SubmittedDate], [t0]. [Project_Type] a partir de [DBO]. [Projectos] AS [t0] LEFT OUTER JOIN [Dbo]. [PROJECT_NOTES] AS [t1] NO 1 = 1 ONDE ([t1]. [Notas] como @ p0) E ([T0] .SubmittedDate]> = @ p1) e ([t0]. [SubmittedDate] <@ p2) E ([t0]. [PROVIDER_ID] = @ P3) E ([t0]. [CATEGORY_ID] IS NULL)) AS [t2] Onde [t2]. [ROW_NUMBER] ENTRE @ P4 + 1 E @ + @ p4 p5 POR ORDEM [t2]. [ROW_NUMBER] 'N' @ p 0 VARCHAR (9), @ p1 de data e hora, data e hora @ P2, 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 retorna todos os mutiples do 1-muitos nos resultados. Eu encontrei como fazer um Exists
em LINQ a partir daqui. http: / /www.linq-to-sql.com/linq-to-sql/t-sql-to-linq-upgrade/linq-exists/
Aqui está a LINQToSQL usando Exists
:
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;
A instrução SQL gerado:
exec sp_executesql N'SELECT COUNT (*) AS [valor] de [dbo]. [Projetos] AS [t0] ONDE (EXISTE (SELECCIONAR NULL AS [vazio] DE [dbo]. [PROJECT_NOTES] AS [t1] ONDE ([T1] .PROJECT_ID] = ([t0]. [PROJECT_ID])) E ([t1]. [Notas] como @ p0))) E ([T0]. [SubmittedDate]> = @ p1) e ([t0]. [SubmittedDate] <@ p2) E ([t0]. [PROVIDER_ID] = @ P3) E ([t0]. [CATEGORY_ID] IS NULL) 'N' @ p 0 VARCHAR (9), @ p1 de data e hora, data e hora @ P2, P3 @ int', @ p0 = '% chicago%', @ p1 = '' 2000/09/02 00: 00: 00: 000 '', @ p2 = '' 2009-03-02 00: 00: 00: 000 '', @ p3 = 1000
Eu fico um tempo limite SQL do databind()
de usar Exists
.
Solução
parece estar voltando várias linhas de projeto
Sim, é assim que se juntar obras. Se um projeto tem 5 notas correspondentes, ele mostrar-se 5 vezes.
E se o problema é - "Join" é o idioma errado
Você deseja filtrar os projectos para aqueles cujas notas contêm determinado texto:
var query = db.Project
.Where(p => p.Notes.Any(n => n.NoteField.Contains(searchString)));
Outras dicas
Você vai ter que usar o método de extensão DefaultIfEmpty. Há algumas perguntas sobre SO já que mostram como fazer isso. Aqui está um bom exemplo: