如何改进此EF查询?

时间:2015-04-03 14:41:45

标签: c# .net entity-framework

.NET 3.5 Framework上的C#

所以,我正在尝试进行有效的查询,以查找要从我的系统中清除的所有电子邮件。应该清除的是已经尝试的电子邮件(Datetime列LastAttempted不为null)和保留的天数(int列RetentionDays)已经过去。这有效,但我知道它会把所有东西都拉回来并在内存中过滤。

这就是我现在所拥有的

        var emails = dbContext.Emails
            .Where(x => x.LastAttempted.HasValue == true)
            .ToList()
            .Where(x => ((DateTime)x.LastAttempted).AddDays(x.RetentionDays) <= DateTime.Now);

如何更新此内容,以便仅从SQL Server中提取我关注的记录?

4 个答案:

答案 0 :(得分:4)

使用EntityFunctions.AddDays在EF查询中为DateTime添加天数。

var emails = dbContext.Emails
    .Where(x => x.LastAttempted.HasValue &&
        EntityFunctions.AddDays(x.LastAttempted, x.RetentionDays) 
        <= DateTime.Now);

答案 1 :(得分:1)

这部分查询:

dbContext.Emails
         .Where(x => x.LastAttempted.HasValue == true)
         .ToList();

将在sql server中执行,并且在调用ToList时将返回内存集合。

然后是查询的最后一部分:

.Where(x => 
    ((DateTime)x.LastAttempted).AddDays(x.RetentionDays) <= DateTime.Now);

将在内存集合中的上述项目中执行。

所以问题依赖于查询的最后一部分。您可以使用AddDays的方法EntityFunctions来避免这种情况,并避免在内存集合中进行第二次过滤。这可以完成如下:

dbContext.Emails
         .Where(x => x.LastAttempted.HasValue == true &&
             EntityFunctions.AddDays(x.LastAttempted, x.RetentionDays) 
                 <= DateTime.Now);

答案 2 :(得分:0)

在查询末尾移动ToList()

var now = DateTime.Now;
var emails = dbContext.Emails
.Where(x => x.LastAttempted.HasValue && 
    EntityFunctions.AddDays((DateTime)x.LastAttempted, x.RetentionDays) <= now).
    ToList();

答案 3 :(得分:0)

您可以随时直接查询数据库,如下所示:

var items = dbContext.Database.SqlQuery<Email>("select * from Emails where LastAttempted Is Not Null And LastAttempted + RetentionDaya >= GetDate()", new SqlParameter[0]);

注意:我对您的实体,表格和列名称做了一些猜测。