Linq To SQL C#.NET 3.5の左外部結合と存在
-
03-07-2019 - |
質問
一意の親行を返すLINQToSQLからの左外部結合の変換に固執しています。
2つのテーブル(Project、Project_Notes、およびProject_IDによってリンクされた1対多の関係)があります。 2テーブルの複数の列でキーワード検索を行っていますが、Project_Notesの列にキーワードが含まれている場合にのみ、一意のプロジェクトを返します。このlinqtoSQlシーケンスを実行していますが、複数のプロジェクト行を返しているようです。おそらくLINQでExist
を行うのでしょうか?それとも、ある種のグループバイですか?
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;
プロファイラーから生成されたSQL
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 WHERE([t1]。[NOTES] LIKE @ p0)AND ([t0] .SubmittedDate] <!> gt; = @ p1)AND([t0]。[SubmittedDate] <!> lt; @ p2)AND([t0]。[PROVIDER_ID] = @ p3)AND([t0]。[CATEGORY_ID] IS NULL))AS [t2] WHERE [t2]。[ROW_NUMBER] BETWEEN @ 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 = 373620、@ p5 = 20
このクエリは、結果に1対多の関係のすべての複数要素を返します。ここからLINQでExists
を実行する方法を見つけました。 http:/ /www.linq-to-sql.com/linq-to-sql/t-sql-to-linq-upgrade/linq-exists/
databind()
を使用したLINQToSQLは次のとおりです。
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;
生成されたSQLステートメント:
exec sp_executesql N'SELECT COUNT(*)AS [value] FROM [dbo]。[PROJECTS] AS [t0] WHERE (EXISTS(SELECT NULL AS [EMPTY] FROM [dbo]。[PROJECT_NOTES] AS [t1] WHERE ([t1] .PROJECT_ID] =([t0]。[PROJECT_ID]))AND([t1]。[NOTES] LIKE @ p0)))AND ([t0]。[SubmittedDate] <!> gt; = @ p1)AND([t0]。[SubmittedDate] <!> lt; @ 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
<=>を使用すると、<=>からSQLタイムアウトが発生します。
解決
複数のプロジェクト行を返しているようです
はい、それが参加の仕組みです。プロジェクトに一致するメモが5つある場合、5回表示されます。
問題が発生した場合-<!> quot; Join <!> quot;間違ったイディオムです!
特定のテキストをノートに含むプロジェクトにフィルターをかけたい場合:
var query = db.Project
.Where(p => p.Notes.Any(n => n.NoteField.Contains(searchString)));
他のヒント
DefaultIfEmpty拡張メソッドを使用する必要があります。 SOには、これを行う方法を示すいくつかの質問が既にあります。次に例を示します。