我正在使用这行代码:
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()));
使用这行代码我基本上都在进行搜索,当globalSearch
为string
并且BankAccount
和Description
之类的列为{时,它似乎正常工作{1}},varchar
globalSearch
或Int
( - 2233或4/9/2013)列为DateTime
,CheckAmount (int)
时{1}} ,ClearedDate (DateTime)
,它会返回0行,如果SentDate (DateTime)
与globalSearch
中的int
匹配,则可以正常工作!
我做错了什么?
我在SQL Server中运行了这个查询:
ChckNumber
我的所有日期都将于2017年9月9日返回如果SELECT CONVERT(VARCHAR(MAX), ClearedDate) FROM myTable
是2017年9月10日,则可以使用,但它不适用于我需要的格式:9/9/2017
答案 0 :(得分:7)
你不应该关心globalSearch是否是一个Int因为你应该总是将它转换为一个字符串,除非是DateTime而你不应该关心一个列是一个varchar还是一个Int,因为你总是将列转换为字符串,除非DateTime
请注意,我根据您的评论做出假设,即您只是比较月,日和年,而不关心ClearedDate的时间
我发现您的代码存在三个潜在问题:
以下是更易读的代码,它将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,则可以使用新的Null Propagation Operator来防止错误,如果您的任何列现在或将来都允许空值:
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));
为CheckAmount转换globalSearch ToString包含可以解决您的问题,使您的代码更具可读性并防止空值,如果它不能修复bug,将使调试变得更容易。
答案 1 :(得分:2)
您的代码将返回查询中第一个字段与查询字词匹配的行。这是一个现实的要求吗?我建议不要。查询术语必须指向已知的特定字段。
您是否真的有兴趣将查询字词作为字段内容的子字符串?至少在整数和日期字段的情况下,这似乎不太可能,但是由于您没有说明您的查询字词可以包含的值,因此无法确定。
没有必要转换varchar字段.ToString()
,因为它们已经是字符串。同样,如果您在查询DateTime
或Integer
字段时提供了相应类型的查询字词,则您也不需要转换它们(假设您实际上并未查询子字符串) 。这将避免使用空字段值的问题,并将删除更多的冗余处理。
您可能需要在考虑这些要点的情况下重新设计查询。而不是使用"一个尺寸适合所有"查询对象,我建议你采取更深思熟虑的方法。
例如,您可以创建一个查询对象,其中包含每个查询字段的可空属性。
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对象,并将其上的任何非null属性与相应的实体属性进行匹配。
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 :(得分:2)
对于迟到的答案感到抱歉
不要使用ToString for Numerics
而是检查globalsearch字符串是否为NUmeric,
如果是数字,则将其转换为必需字段,如整数或双精度。 至于相关的DateTime,
使用Date格式化程序作为p.ClearedDate.ToString(" dd / MM / yyyy")并且不需要格式化globalsearch,因为它将采用给定的格式
我的解决方案可能是这个,
query = query.Where(p => p.ChckNumber == int.TryParse(globalSearch.ToString,out num)?num:globalSearch.ToString(); || p.BankAccount.ToString()。包含(globalSearch.ToString())|| p.Description.ToString()。包含(globalSearch.ToString())|| p.CheckAmount == decimal.TryParse(globalSearch.ToString,out num)?num:globalSearch.ToString(); || p.ClearedDate.ToString(" dd / MM / yyyy")。包含(globalSearch.ToString())|| p.SentDate.ToString(" DD / MM / YYYY&#34)。包含(globalSearch.ToString()));
答案 3 :(得分:1)
如果您正在寻找正确的日期格式,请试试这个。
SELECT CONVERT(VARCHAR(10), SYSDATETIME(), 103)
答案 4 :(得分: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()));
答案 5 :(得分:1)
尝试设置日期部分的格式
p.ClearedDate.ToString("dd/MM/yyyy").Contains(globalSearch.ToString("dd/MM/yyyy"))
还可以尝试使用linq Pad或类似工具或任何linq帮助扩展来查看SQL出现的内容
答案 6 :(得分:1)
您应该根据您的要求使用格式。全部日期时间格式由数字编码。
例如,110 - > MM-DD-YYYY
SELECT CONVERT(VARCHAR(MAX), ClearedDate, 110) FROM myTable