2012-04-27 69 views
2

我有這個功能的Linq-to-Sql語句。如何優化這個孩子檢索linq-to-sql語句?

​​

它給了我所選的孩子ID,根據要求,但我一直在運行SQL事件探查器。

此聲明似乎向每個selectedParentId的數據庫發送一個單獨的請求,這對我而言似乎不太合適。

有沒有一種方法可以重構此聲明以最小化服務器的流量?我應該採取一種不同的方法,還是這樣做呢?

編輯

感謝您的指導。

這對我的跟蹤輸出的解釋是一個錯誤,Linq-To-SQL對SQLServer 2005做出了完全合理的聲明,就像它對SQLServer 2008一樣。問題在於別處。

+0

對於selectedParentIds有什麼奇怪的嗎?如果你對它做一個ToList()會發生什麼?例如.chere(c => selectedParentIds.ToList()。Contains(c.parentId))。 – Phil 2012-04-27 17:10:24

回答

1

對SQL 2008使用LINQ to SQL的相同查詢生成單個SQL查詢。你能測試SQL Server 2008嗎?

例如:

IEnumerable<int> list = new List<int>{1,2,3}; 

Models.Where (m => list.Contains(m.Id)).Select (m => m.Id).ToList(); 

主要生產

-- Region Parameters 
DECLARE @p0 Int = 1 
DECLARE @p1 Int = 2 
DECLARE @p2 Int = 3 
-- EndRegion 
SELECT [t0].[Id] 
FROM [Models] AS [t0] 
WHERE [t0].[Id] IN (@p0, @p1, @p2) 

並採用實體框架同樣的事情產生

SELECT 
[Extent1].[Id] AS [Id] 
FROM [dbo].[Models] AS [Extent1] 
WHERE [Extent1].[Id] IN (1,2,3) 

所以沒有能夠檢查這對SQL 2005,我米會冒險並說,除非升級服務器,否則沒有什麼可以做的。

+0

是的,但我懷疑客戶是否準備升級。我猜對於SQL Server 2008框架使用「表值參數」http://msdn.microsoft.com/en-us/library/bb675163.aspx – Jodrell 2012-04-27 16:53:23

+3

我不認爲LINQ到SQL會根據版本產生不同的結果您正在使用的服務器。如果用「.ToString()」替換「.ToList()」,則可以在調試器中看到生成的查詢。 – RobSiklos 2012-04-27 17:05:18

+0

有趣的是,2005年生成的語句都是完全有效的TSQL。 – Jodrell 2012-04-27 17:05:53

1

這是否會產生任何不同?

public IEnumerable<int> GetChildIds(IEnumerable<int> selectedParentIds) 
{ 
using (var context = new MyContext()) 
{ 
    return context.Children 
     .Where(c => selectedParentIds.Any(p => p == c.parentId)) 
     .Select(c => c.Id) 
     .ToList(); 
} 
} 
+0

我在運行時得到一個'System.NotSupportedException',消息「本地序列不能用於除Contains運算符之外的查詢運算符的LINQ to SQL實現。「它是否與SQL2008 +服務器一起工作? – Jodrell 2012-04-27 17:01:52

+0

另外,它的合法的引用嵌套閉包的方式,在嵌套閉包方面似乎。似乎是有效的Linq,所以我會記住。 – Jodrell 2012-04-27 17:03:45

+0

該查詢不起作用使用Linq to SQL來對付SQL 2008,但是使用Entity Framework,雖然這是一個更復雜和效率更低的查詢。 – Phil 2012-04-27 17:04:47

0

如果您收到不同的輸出爲不同版本的SQL Server的你總是可以嘗試這樣的事情

public IEnumerable<int> GetChildIds(IEnumerable<int> selectedParentIds) 
{ 
    using (var context = new MyContext()) 
    { 
     var query = context.Children; 
     foreach (var id in selectedParentIds) 
     { 
      query = query.Where(q => q.parentId == id); 
     } 

     return query.Select(q => q.Id) 
        .ToList(); 
    } 
} 

我不再有SQL Server 2005中的一個實例,以測試這對(SQL即使是初始代碼,使用兼容模式的Server 2008 R2仍然會生成單個查詢,但是無論您使用的是哪種版本的SQL Server,這應該會生成一個包含多個where子句的單個查詢。