2012-06-07 79 views
3

我正在編寫一個用戶界面,允許某人按他們的名字和/或姓氏查找用戶。例如,如果您輸入名字「Mike」和輸入姓氏「Jo」,則返回「Mike Jones」,「Mike Johnson」和「Mike Jobs」。我用下面的LINQ聲明中搜索:使用實體框架在數據庫中搜索文本

var users = (from u in context.TPM_USER 
      where u.LASTNAME.ToLower().Contains(LastName.ToLower()) 
      && u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()) 
      select u); 

(有可能會或可能不會是一個更好的辦法做到不區分大小寫條款,但這似乎工作)

問題如果用戶輸入名字或姓氏,但是然後將其他字段留空。如果我爲名字輸入「Mike」並將姓氏字段留空,我想要返回所有Mikes,而不管他們的姓氏是什麼。上述查詢不會返回任何結果,除非這兩個字段至少填充了某些內容。

我想:

var users = (from u in context.TPM_USER 
      where (LastName == "" || u.LASTNAME.ToLower().Contains(LastName.ToLower())) 
      && (FirstName == "" || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())) 
      select u); 

不過,我仍然沒有結果,除非這兩個字段填寫。我在調試器下驗證LastName == ""確實如此。

UPDATE:

我做了一些更多的調試,這實際上是一個Oracle的問題。正在生成的查詢是:

--Replaced the field list with * for brevity 
SELECT * FROM TPMDBO.TPM_USER "Extent1" 
    WHERE (('jones' = '') OR ((INSTR(LOWER("Extent1".LASTNAME), LOWER('jones'))) > 0)) AND (('' = '') OR ((INSTR(LOWER("Extent1".FIRSTNAME), LOWER(''))) > 0)) 

乍一看似乎是正確的。但是,Oracle似乎沒有正確地短路短語('' = '')。實際上,如果我這樣做:

select * from TPM_USER where '' = '' 

我得到零行。我不夠了解Oracle如何編寫,但這兩種方式都是實體框架方言錯誤。

回答

8

只需添加謂詞條件:

var users = from u in context.TPM_USER select u; 
if (!string.IsNullOrWhiteSpace(FirstName)) 
    users = users.Where(u => u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())); 
if (!string.IsNullOrWhiteSpace(LastName)) 
    users = users.Where(u => u.LASTNAME.ToLower().Contains(LastName.ToLower())); 

或僅LASTNAME謂詞作爲條件之一。

+0

謝謝!這樣可行。我有點好奇,爲什麼你必須跳過這些環節。如果沒有其他人提出涉及單個LINQ語句的更簡潔的方法,我會接受這個答案。 –

+0

儘管這是一個Oracle問題,但我將其標記爲答案,因爲它提供了最佳的解決方法。然而,史蒂夫值得幾點確認這個*應該在SQL Server中工作。 –

+0

對於它的價值,imo這是一種更清晰的方式:它導致最小化的LINQ語句,並且更具可讀性。另外,'IsNullOrWhiteSpace'是(我認爲)比'=='''更強大的檢查。 – JKomusin

0

你可以簡單地創建一個條件語句在你的查詢:

if (String.IsNullOrWhiteSpace(LastName) && !String.IsNullOrWhiteSpace(FirstName)) 
{ 
    var users = (from u in context.TPM_USER 
    where (u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())) 
    select u); 
} 
else if (String.IsNullOrWhiteSpace(FirstName) && !String.IsNullOrWhiteSpace(LastName)) 
{ 
    var users = (from u in context.TPM_USER 
    where (u.LASTNAME.ToLower().Contains(LastName.ToLower())) 
    select u); 
} 
+0

這似乎可能會變得非常混亂,如果我有兩個以上的領域,很快就會變得非常混亂。 –

+0

@GertArnold頂部的答案與我的邏輯完全相同,不是嗎? – lkaradashkov

2

你確定名字和姓氏不爲空?

你可以嘗試這樣的而不是寫它...

string LowerFirstName = (FirstName + "").ToLower(); 
string LowerLastName = (LastName + "").ToLower(); 

var users = (from u in context.TPM_USER 
      where (LowerLastName == "" || u.LASTNAME.ToLower().Contains(LowerLastName)) 
      && (LowerFirstName == "" || u.FIRSTNAME.ToLower().Contains(LowerFirstName)) 
      select u); 
+0

是的。這些值來自ASP.NET TextBox控件,正如我所提到的,我確認它們確實是調試器下的「」。 –

+0

@MikeChristensen - 奇怪。它應該工作。我之前在Linq和SQL中都編寫過這樣的代碼。它的效率和重點。 –

+0

我不知道它是否與我使用的Oracle實體框架驅動程序有關。我希望我能看到正在生成的SQL,但我不知道如何做到這一點。 –

1

僅供參考,如果有人跑進這個問題與甲骨文,這裏有一個解決方法:

var users = (from u in context.TPM_USER 
      where (LastName == null|| u.LASTNAME.ToLower().Contains(LastName.ToLower())) 
      && (FirstName == null || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())) 
      select u); 

這將被轉換到:

'' is null 

在SQL中,Oracle將其解釋爲true。

+1

如果您需要在包含/的endsWith/StartWith始終不區分大小寫進行搜索,您可以設置CaseInsensitiveLike選項設置爲「true」,並使用下面的代碼: u.LASTNAME.Contains(姓氏) 的CaseInsensitiveLike選項可以打開方式如下: var config = Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfig.Instance; config.QueryOptions.CaseInsensitiveLike = true; – Devart

+0

@Mike無論是FirstName還是LastName包含值,都會返回預期結果。如果First和Last Name都包含值,則返回null。你能幫我解決這個問題嗎?我有一個int和一個字符串列。 –

0

也許你可以嘗試檢查搜索條件的長度,看它是否在Oracle PL/SQL中工作。

var users = (from u in context.TPM_USER 
     where ((LastName ?? "").Trim().Length == 0 || u.LASTNAME.ToLower().Contains(LastName.ToLower())) 
     && ((FirstName ?? "").Trim().Length == 0 || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())) 
     select u); 
相關問題