LINQ to Entities:LINQ查询中的年龄计算导致“方法无法转换为商店表达式”

时间:2012-05-15 13:26:02

标签: .net linq linq-to-entities

使用LINQ to Entities,我需要从PersonTable获取记录WHERE年龄介于AgesFrom和AgesTo之间。问题是,我需要从DateOfBirth和特定的DateToCalculate计算它们的Age,它们都存储在数据库中。

例如。 PersonTable:DateOfBirth = 01/04 / 1972,DateToCalculateAge = 25/12/2011

.Where(0 < o.FormDate.AddYears(-agesFrom).CompareTo(o.FormDate.Subtract(o.Person.DateOfBirth)) &&
       0 > o.FormDate.AddYears(-agesTo).CompareTo(o.FormDate.Subtract(o.Person.DateOfBirth));
// ----------------------- OR ------------------------
.Where(agesFrom <= CalculateAge(o.Person.DateOfBirth.Value, o.FormDate) &&
       agesTo >= CalculateAge(o.Person.DateOfBirth.Value, o.FormDate);

对于我提供的代码,我得到以下异常:“LINQ to Entities无法识别方法'System.DateTime AddYears(Int32)'方法,并且此方法无法转换为商店表达式。”

我理解一旦LINQ将Query传递给db,我尝试使用的方法就无法翻译。有没有解决这个问题?我可以在点击数据库后过滤,但想避免那种瓶颈。我还想过添加一个sql函数来为我做这个计算,但是想先耗尽LINQ的可能性。

这里有一篇不错的帖子详细说明了如何在查询之前进行年龄计算更好: Shortest way to check for age filter in LINQ?但是在我的情况下,我不是从DateTime.Now计算年龄,而是从数据库中的日期开始计算年龄。

2 个答案:

答案 0 :(得分:8)

由于您使用的是LINQ to Entities,首选解决方案是使用System.Data.Objects.EntityFunctions中定义的方法(EF版本6的 更新: 使用DbFunctions代替),查询表面将成功将它们转换为SQL。在这种情况下,你想采取例如这样:

o.FormDate.AddYears(-agesFrom)
          .CompareTo(o.FormDate.Subtract(o.Person.DateOfBirth))

并将其转换为类似

的内容
EntityFunctions.DiffMinutes(
    EntityFunctions.AddYears(o.FormDate, -agesFrom),
    EntityFunctions.AddSeconds(
        o.FormDate, 
        EntityFunctions.DiffSeconds(o.FormDate, o.Person.DateOfBirth)
    )
)

我不确定上述内容是否真的正确,因为它确实伤害了我的眼睛。

答案 1 :(得分:0)

您不能在LINQ to Entities中使用这些方法。但是,如果查询是在内存中完成的,则可以。尝试在.ToList()

之前使用.Where
.ToList().Where(0 < o.FormDate.AddYears(-agesFrom)
         .CompareTo(o.FormDate.Subtract(o.Person.DateOfBirth)) && 0 > o.FormDate.AddYears(-agesTo)
         .CompareTo(o.FormDate.Subtract(o.Person.DateOfBirth));

.ToList().Where(agesFrom <= CalculateAge(o.Person.DateOfBirth.Value, o.FormDate) 
          && agesTo >= CalculateAge(o.Person.DateOfBirth.Value, o.FormDate);

这样.ToList()会将查询带到内存中,您就可以使用这些方法了。

如果您拥有庞大的数据库,那么性能会受到影响,但它会起作用。