如何在动态linq中格式化日期文字?

时间:2010-02-18 11:46:05

标签: c# linq datetime dynamic

我正在使用动态Linq来返回用户输入搜索条件的数据。除了用户选择的日期之外,我的查询工作正常。我目前的代码是:

        StringBuilder whereClause = new StringBuilder();

        if (startDate.HasValue || endDate.HasValue)
        {
            DateTime searchStartDate = startDate.HasValue ? startDate.Value : DateTime.MinValue;
            DateTime searchEndDate = endDate.HasValue ? endDate.Value : DateTime.MaxValue;

            whereClause.AppendFormat("Date >= {0} && Date <= {1}",
                searchStartDate.Date.ToUniversalTime(),
                searchEndDate.Date.ToUniversalTime());
        }

        if (whereClause.Length > 0)
        {
            return (from p in this.repository.GetQueryable<Party>() select p)
                .Where(whereClause.ToString())
                .ToList();
        }

查询会因为在DateTime字段和Int32字段之间进行比较而失败,这意味着查询已将我的日期文字解释为整数。

我应该如何格式化日期?

3 个答案:

答案 0 :(得分:8)

使用

.Where("Date >= @0 && Date <= @1",
                searchStartDate.Date.ToUniversalTime(),
                searchEndDate.Date.ToUniversalTime())

代替。

回复Val的评论:

好的,那么你可以这样做:

whereClause.AppendFormat("Date.ToString() >= \"{0}\" && Date.ToString() <= \"{1}\"",
                searchStartDate.Date.ToUniversalTime(),
                searchEndDate.Date.ToUniversalTime());

您必须将查询中的日期转换为字符串,然后将其与带引号的字符串文字进行比较。如果没有引号,解析器就会将插入到where子句中的数字作为整数进行排序 - 这应该解释您最初得到的错误。

答案 1 :(得分:1)

为什么要解析LINQ表达式中的字符串? LINQ的全部意义是避免这种情况。

var q =  from p in this.repository.GetQueryable<Party>() select p;

if (startDate.HasValue || endDate.HasValue) 
{ 
  var searchStartDate = startDate.HasValue ? startDate.Value : DateTime.MinValue; 
  var searchEndDate = endDate.HasValue ? endDate.Value : DateTime.MaxValue; 
  return 
         q.Where (p=> p.Date >= searchStartDate.ToUniversalTime() 
                   && p.Date <= searchEndDate.ToUniversalTime()).ToList();
} 
return q.ToList();

更新: 回应评论:我正在运行时构建那个。问题不是运行时与编译时;它是“在字符串中”与“在代码中”。 StringBuilder允许您追加文本; LINQ让链接lamdbas。这一切都是一样的 - 除了你的代码是类型安全的,并使用lambdas进行语法检查。

为了进一步说明这个概念,下面的代码编译和编译。运行正常,并允许您根据oddsOnlylowerLimit的值更改Where子句。

int[] nums = {1,2,3,4,5,6,7,8,9,10};

bool oddsOnly = true; 
bool lowerLimit = 5;

var q = from i in nums select i;

if (oddsOnly)
    q = q.Where( n=> n%2 == 1);

if (lowerLimit != 0)
    q = q.Where( n=> n >= lowerLimit);

foreach(var i in q)
    Console.WriteLine(i);

根据您设置这些值的方式,它将使用零个,一个或两个where子句。

答案 2 :(得分:1)

Dynamic LINQ字符串需要看起来像:

"Date >= DateTime(2015, 10, 21)"

http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library提到的下载中的DynamicQuery项目的文档中提到了这一点。

请注意,new构造函数之前没有DateTime

我试过这个并且它有效。我正在使用Telerik的RadGrid控件来实现ASP.NET AJAX。网格构建过滤器字符串,我需要将过滤器添加到我的查询中,以使用LINQ to Entities在数据库中执行过滤器。问题是生成的过滤器需要稍微更改才能使用LINQ to Entities而不是LINQ to Objects。它正在执行DateTime.Parse(),LINQ to Entities不支持。