2017-03-02 57 views
4

我工作這行代碼:可查詢的WHERE包含字符串,整數,日期時間

query = query.Where(p => 
    p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
    p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
    p.Description.ToString().Contains(globalSearch.ToString()) || 
    p.CheckAmount.ToString().Contains(globalSearch) || 
    p.ClearedDate.ToString().Contains(globalSearch.ToString()) || 
    p.SentDate.ToString().Contains(globalSearch.ToString())); 

有了這一行代碼,我基本上是做一個搜索,它似乎好工作時globalSearchstring和像BankAccountDescription柱是varchar,然而,當globalSearchIntDateTime(-2233或2013年4月9日),用於列CheckAmount (int)ClearedDate (DateTime)SentDate (DateTime),則返回0行,並且如果globalSearch一個int在匹配0 它的工作原理!

我在做什麼錯?

我跑了此查詢的SQL Server:

SELECT CONVERT(VARCHAR(MAX), ClearedDate) FROM myTable

和我所有的日期返回2017年9月9日如果globalSearch是2017年9月10日它的工作原理,但它不會對我的需要的格式工作: 9/9/2017

+0

因此,如果用戶鍵入「2」,你想返回任何數字或日期字段包含2(如112號或日期01/03/2017)的所有項目。似乎不是很有用。 – Evk

+0

請檢查什麼查詢是在sql探查器的幫助下觸發的。這會給你一個如何調整你的linq的想法。我猜測它與ToString()如何將數據轉換爲字符串以及使用哪種格式有關。 – Gurpreet

+0

嘗試逐步調試代碼,1-嘗試檢查「Tostring」方法是否在輸入數據上正常工作。 2 - 嘗試檢查sql-server數據庫中的日期時間格式是否與您的日期時間輸入一致 –

回答

7

如果globalSearch是一個Int,你應該不會在乎,因爲你應該總是將它轉換爲一個字符串,除非DateTime和你不應該在乎一列是varchar還是Int,因爲你總是轉換列到字符串,除非DateTime。

注意,我都假設的基礎上,你的意見,你是比較剛一個月,一天,一年不關注的時候了ClearedDate

我看到你的代碼三個潛在的問題:

  1. 你不轉換globalSearch爲列中輸入字符串CheckAmount
  2. 你不打電話的ToString之前檢查空您的任何列,也許對所有列不允許NULL
  3. 您的代碼是沒有非常可讀,人眼難以發現不一致。

這裏是更具可讀性的代碼轉換globalSearch每次都因爲再次,你不globalSearch轉換爲CheckAmount字符串中的字符串一次:如果您正在使用

var gsStr = globalSearch.ToString(); 
var gsDate = DateTime.MinDate; 
if(globalSearch.GetType() == typeof(DateTime)) 
{ 
    gsDate = globalSearch; 
} 
query = query.Where(p => p.ChckNumber.ToString().Contains(gsStr) 
|| p.BankAccount.ToString().Contains(gsStr) 
|| p.Description.ToString().Contains(gsStr) 
|| p.CheckAmount.ToString().Contains(gsStr) 
|| p.ClearedDate.Date == gsDate.Date 
|| p.SentDate.ToString().Contains(gsStr)); 

C#6.0,你可以使用新的空傳播運營商從錯誤中保護您的任何列也允許空值,現在或將來:

var gsStr = globalSearch.ToString(); 
var gsDate = DateTime.MinDate; 
if(globalSearch.GetType() == typeof(DateTime)) 
{ 
    gsDate = globalSearch; 
} 
query = query.Where(p => p.ChckNumber?.ToString().Contains(gsStr) 
|| p.BankAccount?.ToString().Contains(gsStr) 
|| p.Description?.ToString().Contains(gsStr) 
|| p.CheckAmount?.ToString().Contains(gsStr) 
|| p.ClearedDate?.Date == gsDate.Date 
|| p.SentDate?.ToString().Contains(gsStr)); 

轉換globalSearch的toString CheckAmount包含可以解決您的我使得你的代碼更具可讀性和防止空值,如果它沒有修復bug,它將更容易調試。

+0

這個問題有sql標記,所以有可能使用了實體框架,如果是的話,使用.ToString()的代碼很可能不會在那裏工作。 –

+0

我在SQL Server中運行此查詢SELECT CONVERT(VARCHAR(MAX),ClearedDate)FROM myTable和我所有的日期返回Sep 9 2017如果globalSearch是2017年9月10日它可以工作,但它不適用於我需要的格式9/9/2017 – user979331

+0

@ user979331我更新了我的答案,與DateTime.Dates比較 –

1

嗨,如果你正在尋找你的日期正確的格式試試這個。

SELECT CONVERT(VARCHAR(10), SYSDATETIME(), 103) 
1

單字符日期格式。我們可以使用char作爲ToString的參數來指定預設格式。這些是標準格式。

query = query.Where(p => 
p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
p.Description.ToString().Contains(globalSearch.ToString()) || 
p.CheckAmount.ToString().Contains(globalSearch) || 
p.ClearedDate.ToString("d").Contains(globalSearch.ToString()) || 
p.SentDate.ToString("d").Contains(globalSearch.ToString())); 

OR

ToShortDateString()相當於小寫d的ToString( 「d」)

query = query.Where(p => 
p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
p.Description.ToString().Contains(globalSearch.ToString()) || 
p.CheckAmount.ToString().Contains(globalSearch) || 
p.ClearedDate.ToShortDateString().Contains(globalSearch.ToString()) || 
p.SentDate.ToShortDateString().Contains(globalSearch.ToString())); 
1

嘗試格式化您的日期部分

p.ClearedDate.ToString("dd/MM/yyyy").Contains(globalSearch.ToString("dd/MM/yyyy")) 

也可以嘗試linq Pad或類似的工具或任何linq helper擴展來查看SQL將出現什麼

+0

爲什麼在這裏使用'Contains'?這樣的日期字符串將永遠不會包含除本身之外的任何其他日期字符串,並且在這種情況下等於它。因此,對平等的測試會在這裏做同樣的事情,可能會更快。 –

+0

同意你,而不是這個我使用另一種方法,首先檢查日期大於等於和嵌套if(如果可能)檢查小於條件也。即使格式有一點變化(03/03/2017或3/3/2017),這種方法對我來說仍然適用, – Saurabh

1

您應該根據您的要求使用格式。以數字編碼的全部日期時間格式。

例如,110 - > MM-DD-YYYY

SELECT CONVERT(VARCHAR(MAX), ClearedDate, 110) FROM myTable 
2

代碼將返回其在查詢中的第一字段中的查詢詞相匹配的行。這是一個現實的要求嗎?我建議不要。查詢字詞必須註明爲已知的特定字段。

您是否真的有興趣將查詢字詞作爲字段內容的子字符串?至少在整數和日期字段的情況下,這似乎不太可能,但由於您沒有說明查詢字詞可以包含的值,因此無法確定。

沒有必要將varchar字段.ToString()轉換爲已經是字符串。同樣,如果在查詢DateTimeInteger字段時提供適當類型的查詢字詞,則不需要轉換它們(假設您實際上並不查詢子字符串)。這將避免空字段值的問題,並將刪除更多的冗餘處理。

您可能希望重新設計您的查詢並牢記這些要點。我建議你採取更加慎重的方法,而不是使用「一刀切」的查詢對象。

例如,您可以爲每個查詢字段創建一個包含可空屬性的查詢對象。

public partial class AccountQuery 
{ 
    public string CheckNumber { get; set; } 
    public string BankAccount { get; set; } 
    public string Description { get; set; } 
    public int? CheckAmount { get; set; } 
    public DateTime? ClearedDate { get; set; } 
    public DateTime? SentDate { get; set; } 
} 

爲實體模型/ DTO添加一個方法來封裝查詢邏輯。它接受一個AccountQuery對象,並將它的任何非空屬性與相應的實體屬性進行匹配。

public class Account 
{ 
    public string CheckNumber { get; set; } 
    public string BankAccount { get; set; } 
    public string Description { get; set; } 
    public int CheckAmount { get; set; } 
    public DateTime ClearedDate { get; set; } 
    public DateTime SentDate { get; set; } 
    public bool Matches(AccountQuery query) 
    { 
     return (!string.IsNullOrEmpty(query.CheckNumber) && query.CheckNumber == CheckNumber) || 
       (!string.IsNullOrEmpty(query.BankAccount) && query.BankAccount == BankAccount) || 
       (!string.IsNullOrEmpty(query.Description) && query.Description == Description) || 
       (query.ClearedDate.HasValue && query.ClearedDate == ClearedDate) || 
       (query.SentDate.HasValue && query.SentDate == SentDate) || 
       (query.CheckAmount.HasValue && query.CheckAmount == CheckAmount); 
    } 
} 

你的查詢,則變爲,例如:

var aq = new AccountQuery 
{ 
    ClearedDate = DateTime.Today 
}; 
query.Where(p => p.Matches(aq)); 

注意這個查詢的邏輯是不一樣的你原來的代碼,如我上面所指出的,似乎並不現實。

2

對不起,我遲到的回答

不要使用的toString Numerics的

,而不是檢查globalsearch字符串是數字還是不行,

,如果它是一個數,然後將其轉換爲整數一樣必填字段或雙倍。 至於爲DATETIME關注,

使用的日期格式爲p.ClearedDate.ToString(「DD/MM/YYYY」),無需格式化globalsearch因爲這將是在給定的格式

我的解決方案可能是這一點,

查詢= query.Where(p => p.ChckNumber == int.TryParse(globalSearch.ToString,出NUM)民:globalSearch.ToString(); || p'。 BankAccount.ToString()。Contains(globalSearch.ToString())|| p.Description.ToString()。Contains(globalSearch.ToString())|| p.CheckAmount == decimal.TryParse(globa lSearch.ToString,out num)?num:globalSearch.ToString(); || p.ClearedDate.ToString(「dd/MM/yyyy」)。Contains(globalSearch.ToString())|| p.SentDate.ToString(「dd/MM/yyyy」)。Contains(globalSearch.ToString()));