。DateTime.Month上的任何子句

时间:2014-09-24 21:30:00

标签: c# linq datetime dynamics-crm-2011

情况如下:

我正在寻找一个有点大的实体的基本搜索。现在,结果的数量是可管理的,但我预计在使用一两年后会有大量数据,因此这里的性能非常重要。

我正在浏览的对象具有DateTime值,我需要能够输出具有相同月份的所有对象,而不管年份如何。有多个搜索字段可以组合,但其他字段不会导致问题。

我试过了:

if(model.SelectedMonth != null)
{
    contribs = contribs.Where(x => x.Date.Value.Month == model.SelectedMonth);
}

model.Contribs = contribs
    .Skip(NBRESULTSPERPAGE*(model.CurrentPage - 1))
    .Take(NBRESULTSPERPAGE)
    .ToList();

到目前为止,我得到的是“无效”,其中'条件。实体成员正在调用无效的属性或方法。“我想只是调用ToList()但它看起来效率不高,实体也很大。我正在寻找一种干净的方法来完成这项工作。

4 个答案:

答案 0 :(得分:1)

你说:

  

我正在浏览的对象具有DateTime值,我需要能够输出同月的所有对象,无论年份如何

     

...

     

我预计在使用一两年后会有大量数据,因此这里的表现非常重要。

就在那里,你有一个问题。我知道您正在使用LINQ to CRM,但无论您使用何种技术,这个问题实际上都会出现。

根本问题是日期和时间存储在单个字段中。年,月,日,小时,分钟,秒和小数秒都被打包成一个整数,表示自某个时间以来的单位数。对于.NET中的DateTime,这是自1/1/0001以来 ticks 的数量。如果该值存储在SQL DateTime2字段中,则它是相同的。其他数据类型具有不同的开始日期(时期)和不同的精度。但在所有情况下,内部只有一个数字。

如果您正在搜索某个特定年份的值,那​​么您可以从范围查询中获得不错的效果。例如,给出所有值> = 2014-01-01和< 2014年2月1日。这两个点可以映射回数据库中的数字表示。如果该字段具有索引,则范围查询可以使用该索引。

但是,如果您要查找的值只是,那么您提供的任何查询都需要数据库从表中的每个值中提取该月份。这也称为“表扫描”,没有任何索引可以帮助。

可以有效使用索引的查询称为sargable查询。但是,您尝试的查询是不可搜索的,因为它必须评估表中的每个值。

我不知道你对CRM中的对象及其存储有多少控制权,但我会告诉你我通常建议人们直接查询SQL Server:

  • 将月份作为单个整数存储在单独的列中。有时,这可以是基于原始日期时间的计算列,这样您就不必直接输入它。

  • 创建包含此列的索引。

  • 按月查询时使用此列,以便查询可以进行查询。

答案 1 :(得分:0)

这是一个猜测,实际上应该是一个评论,但是在评论中格式化的代码太多了。如果它没有用,我将删除答案。

尝试将model.SelectedMonth移至变量,而不是将其放入Where子句

var selectedMonth = model.SelectedMonth;
if(selectedMonth != null)
{
    contribs = contribs.Where(x => x.Date.Value.Month == selectedMonth);
}

您也可以对CurrentPage执行相同操作:

int currentPage = model.CurrentPage;

model.Contribs = contribs
    .Skip(NBRESULTSPERPAGE*(currentPage - 1))
    .Take(NBRESULTSPERPAGE)
    .ToList();

许多查询提供程序使用变量比使用非相关对象的属性更好。

答案 2 :(得分:0)

model.SelectedMonth的类型是什么?

根据你的代码逻辑,它是可以为空的,看起来它可能是一个结构,所以这有用吗?

if (model.SelectedMonth.HasValue)
{
    contribs = contribs.Where(x => x.Date.Value.Month == model.SelectedMonth.Value);
}

答案 3 :(得分:0)

您可能需要在contrib Entity上创建Month OptionSet属性,该属性通过创建/更新日期属性的实体上的插件填充。然后你可以搜索一个特定的月份,而不是搜索Date字段,它搜索一个int字段。这样也可以轻松地在高级查找中搜索特定月份。

Linq to CRM Provider并不是Linq的完整版本。它通常不支持where语句中属性的任何类型的操作,因为它必须转换为QueryExpressions支持的任何操作。