I have the following partial query
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();
The query works fine except that Month gives me a month and year in the format:
August 2012
and I need it in this format:
08
I changed my code as reflected below:
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();
but now I receive the following error:
Unrecognized expression node: ArrayIndex
Is there a way to do what I am trying to do? Changing the format in the DB is not an option.
Here is the entire query:
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;
}
}
We still don’t really have much context, but I’ll guess at an appropriate answer anyway 🙂
If you’re trying to do a lot of work within a query expression which is being translated to SQL, you may find it’s better to split the query into two parts:
You use
AsEnumerableto effectively flip from using the methods inQueryableto the ones inEnumerable. So you might have:This avoids having to ask the LINQ provider to generate SQL to emulate things like this:
It also means that you can write helper methods which are easily tested outside your query:
Note that
CultureInfo.CurrentCulturemay very well be the wrong culture here, unless you really know that the data stored in your database is in the same culture as your user, which may not be the invariant culture. I think it’s much more likely that you really want to use the invariant culture… or just useCalendar.MonthNames.IndexOf(month).