Linq中的SQL在SQL中没有受支持的翻译

时间:2014-01-14 15:43:23

标签: c# sql linq

我试图在Linq分组。我创建了帮助方法来定义我要分组的周,但是在运行代码时我收到错误消息:

{“Method'Int32 GetWeekNumber(System.DateTime)'没有支持的SQL转换。”} System.SystemException {System.NotSupportedException}

我的Linq查询:

var data = from trans in _dbc.MyStuff
       where
           SqlMethods.Like(trans.SEGMENT2, "00601") && SqlMethods.Like(trans.SEGMENT4, "%")
           &&
           trans.CREATION_DATE >= new DateTime(2013, 01, 01) &&
           trans.CREATION_DATE <= new DateTime(2013, 12, 31)
       group trans by new
       {
           DateYear = (int?)trans.CREATION_DATE.Value.Year,
           DateMonth = (int?)trans.CREATION_DATE.Value.Month,
           DateWeek = (int?)WeekStuff.GetWeekNumber(trans.CREATION_DATE.Value)
       }
           into g
           orderby
               g.Key.DateYear,
               g.Key.DateMonth,
               g.Key.DateWeek
           select new
           {
               DateYear = g.Key.DateYear ?? 0,
               DateMonth = g.Key.DateMonth ?? 0,
               DateWeek = g.Key.DateWeek ?? 0,
               Value = g.Sum(p => p.BASE_TRANSACTION_VALUE) ?? 0,
               Count = g.Sum(p => p.PRIMARY_QUANTITY) ?? 0,
               DateCreated = g.Min(p => p.CREATION_DATE) ?? DateTime.Now,
               Department = g.Min(p => p.SEGMENT2)
           };

我的助手方法:

    public static int GetWeekNumber(DateTime date)
    {
        if (DateTimeFormatInfo.CurrentInfo != null)
        {
            Calendar cal = DateTimeFormatInfo.CurrentInfo.Calendar;
            return cal.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
        }
        return 0;
    }

基本上我想做的就是按周分组,我如何使用辅助方法进行分组(如果我实际上需要帮助方法来实现这一点)?

2 个答案:

答案 0 :(得分:2)

LINQ尝试将您的代码转换为sql并在服务器上运行它。您的自定义方法无法转换为SQL,这是正常的。您可能必须首先填充LINQ查询的结果,然后使用LINQ to objects对其进行分组。

答案 1 :(得分:1)

步骤1.在SQL中创建一个执行所需计算的函数(请注意,这取决于SQL服务器上的@@DATEFIRST设置:

CREATE FUNCTION [dbo].[GetWeek](@dt datetime)
RETURNS int
BEGIN
    RETURN DATEPART( wk, @dt)
END

步骤2.在您的数据上下文类中,添加一个与上面的帮助程序相同的函数,但标记为System.Data.Linq.Mapping.FunctionAttribute属性:

[Function(Name="dbo.GetWeek", IsComposable=true)]
public int GetWeekNumber([Parameter(Name="@dt", DbType="datetime")]DateTime date)
{
  Calendar cal = DateTimeFormatInfo.CurrentInfo.Calendar;
  return cal.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
}

IsComposable=true表示它可以用作其他查询的一部分(即它是一个函数,而不是存储过程)。

步骤3.现在将您的查询更改为使用dbc.GetWeekNumber而不是WeekStuff.GetWeekNumber

或者,您可以将上述方法定义为:

[Function(Name="dbo.GetWeek", IsComposable=true)]
public int GetWeekNumber([Parameter(Name="@dt", DbType="datetime")]DateTime date)
{
  return (int)ExecuteMethodCall(this, (MethodInfo)MethodInfo.GetCurrentMethod(), date).ReturnValue;
}

这样,即使在查询外部调用,它也会触及数据库,而不是在.NET代码中计算它。这个速度较慢(在没有数据库的情况下点击数据库),但是有一个优点就是在命中数据库的代码和不符合数据库的代码之间保持第一天的概念一致。