2015-08-17 63 views
1

我正在寫一種將自定義語言查詢轉換爲Expression樹的方法,以便它可以與任意集合中的Where擴展方法一起使用。這些集合可以是來自內存列表的IEnumerable<T>,或者用於數據庫查詢的IQueryable<T>不區分大小寫的字符串。包含IEnumerable和IQueryable

我的過濾器邏輯涉及到很多字符串包含檢查,以檢查搜索的字符串是否出現在每個對象實例的某個屬性中。我現在使用string.Contains的標準調用,這應該轉換爲SQL Server的SQL LIKE '%...%'(也可能是其他的),在大多數數據庫系統中默認情況下應該不區分大小寫。但是該方法的.NET實現會執行其他操作:區分大小寫,並會從集合中返回其他(較少)對象,因爲這是比較嚴格的比較。

我已經花了最近幾個小時來查找和閱讀有關此主題。 ToLowerToUpperTurkey中將不能正常工作。是否支持SQL生成ToLowerInvariantIndexOf聽起來像是一個更好的選擇。 string.Contains內部調用string.IndexOfIndexOf有另一個接受StringComparison值的超載。但是,這會支持SQL生成嗎?如果我指定Ordinal而不是OrdinalIgnoreCase,它將如何翻譯?

這是非常令人沮喪的。數據庫與.NET中的內存對象不同。但畢竟,Entity Framework將兩個世界合併在一起並將數據庫查詢直接引入C#中。如果通用操作的語義根據它們在運行時的執行方式而改變,它會導致各種錯誤。

+0

這不是我使用EF的經驗。你使用MS SQL Server嗎?你正在查詢的表格的排序規則是什麼? –

+0

任何。我的代碼應該適用於任何數據庫。這是一種開發人員可以在他們的應用程序中使用的庫,以及他們擁有的任何數據庫。或者用戶決定使用。或與內存中的集合。無論如何,我的函數的行爲應該是一樣的。事實上,我不會更改整個數據庫(或表或列)的排序規則,只是讓一個查詢按預期工作。可能有其他查詢需要其他排序規則,這些排序規則會有衝突。非默認排序規則不能成爲解決方案。 – ygoe

+2

歡迎來到泄漏抽象的世界。如果您知道數據庫歸類不區分大小寫,您絕對不希望將帶有類似ToLower的調用的解決方案提供給EF查詢。它禁用索引並阻礙查詢計劃的生成。 –

回答

2

這個問題沒有普遍接受的通用解決方案。不幸的是,你必須意識到你在做什麼以及你在做什麼。

SQL Server與其處理這類查詢的方式不一致的核心原因。它與一致的配置是一致的,但是該配置在.NET環境中並不確定。

沒有一般的方法可以知道如何在沒有實際運行該查詢的情況下如何運行SELECT * FROM users WHERE name LIKE '%foo'

最好的解決方案是避免任何嘗試運行本地查詢的操作,只需總是調用數據庫即可。

+0

所以我需要提供兩種不同的'Contains'檢查實現,以便將表達式轉換爲SQL並在甚至沒有數據庫的應用程序中本地運行它。在不清楚表達式是否仍在數據庫端或已經在本地執行的情況下,開發人員必須決定使用哪個選項。 – ygoe

+0

@LonelyPixel:由於寫入相同的語句有不同的實現,所以您需要選擇單個語句,多個實現(如LINQ to SQL)或者不同語句(針對同一語句),如您在此處所述。 – Guvante

相關問題