簡體   English   中英

String.StartsWith不使用波形符(“〜”)字符LINQ to SQL?

[英]String.StartsWith not working with tilde (“~”) characters LINQ to SQL?

出於某種原因,我使用String.StartsWith()調用IEnumerable.Where()似乎會給出不同的結果,具體取決於它是在LINQ-to-SQL還是標准LINQ(-to-objects)中使用。 如果我在ToList()上添加對同一個調用的調用,我會得到不同的結果:

var withToList = MyDataContext.MyEntities.ToList().Where(entity => entity.Name.StartsWith("~Test: My Test String"));
// withToList.Count() returns 5, which is what I expect.
var direct = MyDataContext.MyEntities.Where(entity => entity.Name.StartsWith("~Test: My Test String"));
// direct.Count() returns 0

這是我的理解是,不像一些在LINQ其他運營商/方法中,其中()方法不需要謂詞是SQL翻譯的; 它在客戶端執行,因此可以是任意.NET代碼。 (我肯定會在其中拋出其他非SQL代碼並獲得成功結果)。 我甚至得到了一個鏈接,其中安德斯自己暗示這應該有效。 有沒有搞錯?

編輯:我發現了問題; 它與我的搜索字符串中存在波浪號有關。 我已更新標題以反映這一點。

此查詢在SQL中執行 - 因此您可能會看到一些奇怪的內容,具體取決於SQL如何處理“LIKE”。 我建議你找出它正在運行的查詢,並嘗試在SQL Management Studio中自己運行它。 在這種情況下,它似乎並不常見 - 它可能是LINQ to SQL中的一個錯誤; 它可能無法正常逃避。 (是否表示SQL LIKE子句中的任何特殊內容?)

任何想要成為數據庫端執行內容的東西需要進行SQL翻譯。 不能包含任意.NET代碼 - 只有LINQ-to-SQL能夠翻譯的代碼。 否則組合會被破壞 - 如果你之后添加一個連接或一個排序等,那么在SQL中進行一些處理會變得非常困難,而在客戶端進行一些處理會混合兩者。 你可以在SQL中做一些, 然后在客戶端做一些。 請注意,您可以使用AsEnumerable作為ToList的替代方法,以使其余查詢在進程中執行。

在Konamiman的建議下,我檢查了日志以查看正在執行的SQL。 這是我所得到的(一個廣泛的例子)。

第一個調用執行:

SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[MyEntity] AS [t0]

這是有道理的,因為過濾發生在客戶端,所以我們需要查詢所有行。

第二個調用執行:

SELECT COUNT(*) AS [value]
FROM [dbo].[MyEntity] AS [t0]
WHERE [t0].[Name] LIKE @p0 ESCAPE '~'

所以,Jon Skeet走在了正確的軌道上; 我遇到了問題,因為我碰巧在我的數據/查詢條件中有波形符號。 這會導致LINQ-to-SQL將其標記為轉義字符,因此不會在搜索中使用它。 這個MSDN線程在解釋原因方面做得不錯 ; 它似乎是LINQ-to-SQL代碼中的一個錯誤。

建議的解決方法是使用LINQ的SQLMethods.Like()方法將轉義字符從“〜”更改為,如下所示:

var direct = MyDataContext.MyEntities.Where(entity => SQLMethods.Like(entity.Name, "~Test: My Test String%", "!");
// direct.Count() now returns 5 as expected

這很有效,但不幸的是,這是一個僅限 LINQ-to-SQL的解決方案。 如果您在LINQ-to-Object版本上嘗試它,則會收到以下錯誤:

System.NotSupportedException : Method 'Boolean Like(System.String, System.String, Char)' 
cannot be used on the client; it is only for translation to SQL.

當Jon Skeet建議使用AsEnumerable()時會發生同樣的事情。

我嘗試在一個方法中包裝我的StartsWith調用,並使用帶有StringComparisonOption的StartsWith,但是這些在LINQ-to-SQL方面不起作用,因為它們不是SQL可翻譯的。 (因此我之前關於Where()方法的假設是不正確的)。

所以:它看起來像(直到這個bug是固定的),你不能有一個搜索功能,無論工作與波浪號人物是不可知的關於LINQ的基本味道。 (如果有方法,請務必發布)。

在第一種情況下, Where謂詞實際上不需要可以轉換為SQL,因為您首先將整個表轉換為內存( ToList )然后進行過濾。

在第二種情況下, Where謂詞需要可以轉換為SQL WHERE子句,因為過濾是在數據庫中完成的。 TheString.StartsWith方法被轉換為SQL LIKE語句。

請記住, 您可以使用DataContext.Log屬性查看生成的SQL 這應該可以幫助您了解它是如何工作的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM