使用DateTime.ParseExact时无法识别的表达式节点:ArrayIndex

时间:2012-08-23 16:25:13

标签: c# linq-to-sql

我有以下部分查询

var finalResults =

    (from o in outerJoin
    orderby o.timeKey.timeKey.Year_Num, o.timeKey.timeKey.Month, o.Key.Key.PlantId, o.timeKey.timeKey.PhysicalUnitId
    select new
    {
        IndicatorName = IndicatorName,
        LocationName = o.timeKey.timeKey.PlantId,
        GroupingName = o.timeKey.timeKey.PhysicalUnitId,
        Year = o.timeKey.timeKey.Year_Num,
        Month = o.timeKey.timeKey.Month, 
        Numerator = o.timeKey.Key.Derate_Hours != null ? o.timeKey.Key.Derate_Hours ?? 0 : 0,
        Denominator = o.timeKey.timeKey.Hours - o.timeKey.Key.Derate_Hours ?? 0,
        Weight = o.timeKey.timeKey.NetMaximumCapacity,                         
    }).ToList();

查询工作正常,但Month以格式给出了一个月份和年份:

August 2012

我需要这种格式:

08

我改变了我的代码,如下所示:

var finalResults =

    (from o in outerJoin
    orderby o.timeKey.timeKey.Year_Num, o.timeKey.timeKey.Month, o.Key.Key.PlantId, o.timeKey.timeKey.PhysicalUnitId
    select new
    {
        IndicatorName = IndicatorName,
        LocationName = o.timeKey.timeKey.PlantId,
        GroupingName = o.timeKey.timeKey.PhysicalUnitId,
        Year = o.timeKey.timeKey.Year_Num,
        Month = DateTime.ParseExact(o.timeKey.timeKey.Month.Split(' ')[0], "MMMM", CultureInfo.CurrentCulture).Month,
        Numerator = o.timeKey.Key.Derate_Hours != null ? o.timeKey.Key.Derate_Hours ?? 0 : 0,
        Denominator = o.timeKey.timeKey.Hours - o.timeKey.Key.Derate_Hours ?? 0,
        Weight = o.timeKey.timeKey.NetMaximumCapacity,                         
    }).ToList();

但现在我收到以下错误:

Unrecognized expression node: ArrayIndex

有没有办法做我想做的事情?不能选择更改DB中的格式。

以下是整个查询:

protected IList<DataResults> QueryData(HarvestTargetTimeRangeUTC ranges)
{
    using (var context = new DataClassesDataContext(_connectionString))
    {
        context.CommandTimeout = 240;                
        const string IndicatorName = "{DFD88372-FB87-49AC-8576-68DCBE7B00E8}";

        List<string> typeCodes = new List<string>() { "D1", "D2", "D3", "DP", "PD", "DM", "D4" };
        DataResults endItem = new DataResults();
        List<DataResults> ListOfResults = new List<DataResults>();

        var results =

            (from v in context.vDimUnits
             join vf in context.vFactEnergyAllocations on v.UnitKey equals vf.UnitKey
             join vd in context.vDimGadsEvents on vf.GadsEventKey equals vd.GadsEventKey
             join vt in context.vDimTimes on vf.TimeKey equals vt.TimeKey
             where typeCodes.Contains(vd.GadsEventTypeCode) 
                && vt.Year_Num >= ranges.StartTimeUTC.Year 
                && vt.Year_Num <= ranges.EndTimeUTC.Year                        
                && v.PhysicalUnitId != "N/A"
                && v.PhysicalUnitId != "UNK"
                && v.PlantId != "UNK" 
                && v.NercUnitType != "WT"
             group vf by new { v.PlantId, v.PhysicalUnitId, v.NetDependableCapacity, vt.Year_Num, vt.Month } into groupItem
             select new
             {
                 groupItem.Key.Year_Num,
                 groupItem.Key.Month,
                 groupItem.Key.PhysicalUnitId,
                 groupItem.Key.NetDependableCapacity,
                 Derate_Hours = groupItem.Sum(x => (float?)x.AllocatedEnergyMwh / groupItem.Key.NetDependableCapacity),
                 groupItem.Key.PlantId,
                 Unit = groupItem.Count()
             });

        var resultHours =

            (from f in
            (from vt in context.vDimTimes
            from v in context.vDimUnits
            where vt.Year_Num >= ranges.StartTimeUTC.Year
                && vt.Year_Num <= ranges.EndTimeUTC.Year 
                && v.PhysicalUnitId != "N/A" 
                && v.PhysicalUnitId != "UNK" 
                && v.PlantId != "UNK" 
                && v.NercUnitType != "WT"
            select new { v.PlantId, v.PhysicalUnitId, vt.Year_Num, vt.Month, vt.TimeKey, v.NetMaximumCapacity }).Distinct()
             group f by new { f.PhysicalUnitId, f.Year_Num, f.Month, f.PlantId } into groupItem
            select new
            {
                 groupItem.Key.PhysicalUnitId,
                 groupItem.Key.Year_Num,
                 groupItem.Key.Month,
                 groupItem.Key.PlantId,
                 groupItem.First().NetMaximumCapacity,
                 Hours = groupItem.Count()
            });

        var serviceHrsResults =

            (from v in context.vDimUnits
             join vf in context.vFactEnergyAllocations on v.UnitKey equals vf.UnitKey
             join vt in context.vDimTimes on vf.TimeKey equals vt.TimeKey
             join vus in context.vDimUnitStates on vf.UnitStateKey equals vus.UnitStateKey

             where vus.UnitStateType != "Active" 
                && vt.Year_Num >= ranges.StartTimeUTC.Year 
                && vt.Year_Num <= ranges.EndTimeUTC.Year
                && v.NetDependableCapacity != 0 
                && v.PhysicalUnitId != "N/A" 
                && v.PhysicalUnitId != "UNK" 
                && v.PlantId != "UNK" 
                && v.NercUnitType != "WT"

             group vf by new { v.PlantId, vt.Year_Num, vt.Month, v.PhysicalUnitId, v.NetDependableCapacity } into groupItem

             select new
             {
                 groupItem.Key.Year_Num,
                 groupItem.Key.Month,
                 groupItem.Key.PhysicalUnitId,
                 groupItem.Key.NetDependableCapacity,
                 groupItem.Key.PlantId,
                 Unit = groupItem.Count()
             });

        var outerJoin1 =

            (from h in resultHours
             join u in results on new { h.PhysicalUnitId, h.Year_Num, h.Month } equals new { u.PhysicalUnitId, u.Year_Num, u.Month } into outer
             from grouping in outer.DefaultIfEmpty()
             select new { timeKey = h, Key = grouping });

        var outerJoin2 =

            (from h in resultHours
             join s in serviceHrsResults on new { h.PhysicalUnitId, h.Year_Num, h.Month } equals new { s.PhysicalUnitId, s.Year_Num, s.Month } into outer2
             from grouping in outer2.DefaultIfEmpty()
             select new { timeKey = h, Key = grouping });

        var outerJoin =

            (from a in outerJoin1
             join b in outerJoin2 on new { a.timeKey.PhysicalUnitId, a.timeKey.Year_Num, a.timeKey.Month } equals new
             {
                 b.timeKey.PhysicalUnitId,
                 b.timeKey.Year_Num,
                 b.timeKey.Month
             } into outer
             from grouping in outer.DefaultIfEmpty()
             select new { timeKey = a, Key = grouping }).Distinct();


        var finalResults =

            (from o in outerJoin
             orderby o.timeKey.timeKey.Year_Num, o.timeKey.timeKey.Month, o.Key.Key.PlantId, o.timeKey.timeKey.PhysicalUnitId
             select new
             {
                IndicatorName = IndicatorName,
                 LocationName = o.timeKey.timeKey.PlantId,
                 GroupingName = o.timeKey.timeKey.PhysicalUnitId,
                 Year = o.timeKey.timeKey.Year_Num,
                 Month = DateTime.ParseExact(o.timeKey.timeKey.Month.Split(' ')[0], "MMMM", CultureInfo.CurrentCulture).Month,
                 Numerator = o.timeKey.Key.Derate_Hours != null ? o.timeKey.Key.Derate_Hours ?? 0 : 0,
                 Denominator = o.timeKey.timeKey.Hours - o.timeKey.Key.Derate_Hours ?? 0,
                 Weight = o.timeKey.timeKey.NetMaximumCapacity,                         
                 }).ToList();

        for (int counter = 0; counter < finalResults.Count; counter++)
        {
            var item = finalResults[counter];
            endItem = new DataResults();
            ListOfResults.Add(endItem);
            endItem.IndicatorName = IndicatorName;
            endItem.LocationName = item.LocationName;
            endItem.GroupingName = item.GroupingName;
            endItem.Year = item.Year;
            endItem.Month = item.Month.ToString();
            endItem.Numerator = item.Numerator;
            endItem.Denominator = item.Denominator;
            endItem.Weight = item.Weight.Value;                    
        }
        return ListOfResults;
    }
}

1 个答案:

答案 0 :(得分:1)

我们仍然没有太多的背景,但无论如何我会猜到一个合适的答案:)

如果您正在尝试在正在转换为SQL的查询表达式中执行大量工作,您可能会发现最好将查询拆分为两部分:

  • 在SQL中完成的部分,尽可能多地过滤并仅指定所需的数据,但采用“原始”格式
  • 在LINQ to Objects中完成的部分,可以使用您需要的任何.NET方法。

您使用AsEnumerable有效地将Queryable中的方法转换为Enumerable中的方法。所以你可能有:

var sqlQuery = from ...
               orderby ...
               select ...;

var finalQuery = sqlQuery.AsEnumerable().Select(entry => new { 
                     // Call whatever methods you like in here
                 });

这避免了要求LINQ提供程序生成SQL来模拟这样的事情:

DateTime.ParseExact(o.timeKey.timeKey.Month.Split(' ')[0], "MMMM", 
                    CultureInfo.CurrentCulture).Month,

这也意味着您可以编写辅助方法,这些方法可以在查询之外轻松测试:

var finalQuery = sqlQuery.AsEnumerable().Select(entry => new { 
                     Month = ConvertYearMonthToMonthNumber(entry.Month),
                     ...
                 });

请注意,CultureInfo.CurrentCulture很可能是错误的文化,除非您确实知道数据库中存储的数据与您的用户处于同一文化中,这可能不是不变的文化。我认为你更有可能想要使用不变文化......或者只是使用Calendar.MonthNames.IndexOf(month)