2014-02-20 314 views
3

我有一個Asp.Net MVC 5網站,我想用LINQ搜索實體。目前我有一個工作搜索功能。但是,我想在運行搜索之前添加一個替換字符串中的字符的功能。這是因爲在波斯語中,單個字符有兩個類似的表示,我想對它們進行搜索。String.Replace in LINQ to Entities

工作代碼是這樣的(一個非常簡化的版本):

var model = db.Restaurants.Where(r => r.Name.ToUpper().Contains(query)); 

我想要做的是這樣的:

query = query.Replace('آ', 'ا'); //couple of other fixes too... 
var model = db.Restaurants.Where(r => r.Name.ToUpper().Replace('آ', 'ا').Contains(query)); 

顯然,這給我的錯誤:

LINQ to Entities does not recognize the method 'System.String Replace(Char, Char)' method, and this method cannot be translated into a store expression 

當前唯一讓我想到的是將替換的字符串存儲到數據庫中並查詢這些字符串秒。我認爲這不是一個乾淨的方法。另一個選擇是在代碼中運行查詢(查詢Restaurant一個接一個),這根本沒有效率。緩存這些值將會有所幫助,但我認爲還有更好的辦法。這就是爲什麼我問這個問題,看看有沒有辦法將這個查詢轉移到數據庫。

+1

這是真的,你顯示*一個非常簡化的版本*,因爲你在你的真實代碼 –

+0

嘗試'FixFarsiChars'方法嘗試'var model = db.Restaurants.AsEnumerable()。where(....' – Damith

+0

其中你可以使用EF版本嗎?在v6中,你可以通過命令攔截器來解決這個問題。 –

回答

4

在實體框架6中,您可以使用命令攔截器。這聽起來很複雜,但他們已經很容易。

首先創建一個實現System.Data.Entity.Infrastructure.Interception.IDbCommandInterceptor的類。只有一個實現方法的問題,其他人可以只是存根:

public class MyCommandInterceptor : IDbCommandInterceptor 
{ 
    public void ReaderExecuting(DbCommand command, 
       DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
     command.CommandText = command.CommandText.Replace("a", "b"); 
    } 

    public void NonQueryExecuting(DbCommand command, 
       DbCommandInterceptionContext<int> interceptionContext) 
    { } 

    ... lots of stubs 
} 

而你在你的應用程序的初始化調用

DbInterception.Add(new MyCommandInterceptor()); 

某處激活攔截。

+0

我絕對必須更加註意這一點,但只是一個簡單的問題。我看到你已經使用了'command.CommandText.Replace(「a」,「b」);'。如果我在我的所有查詢中都使用了這個函數,是不是會阻止我將''a「'插入數據庫或獲取包含'」a「'的字符串? –

+0

這只是一個例子。實際上,你可能應該在查詢中檢查「IN」之類的東西。此外,我認爲你可以安全地取代波斯語字符,因爲它們不會出現在保留字中:) –

+0

非常感謝。我會開始玩它。這似乎是最好的選擇。 –