2017-03-02 39 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()));

相关问题