Sto cercando di implementare l'espressione c # linq che mi consentirà di estrarre dati in base a anni e mesi. L'errore viene generato nel metodo where del mio contesto.
Attualmente sto ricevendo l'errore
System.NotSupportedException: 'Unable to create a constant value of type 'System.Tuple`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. Only primitive types or enumeration types are supported in this context.'
Espressione Linq
var periodTuples = period.ToList() // gives you List<KeyValuePair<int, int[]>>
.SelectMany(kvp =>
kvp.Value.Select(it2 => Tuple.Create(kvp.Key, it2))).ToHashSet(); // to optimize .Contains()
benchmark1Returns = GetViewService<MV_INDEX_PERFORMANCE>()
.Where(x => x.Mtd != null && x.IndexId == benchMark1 && periodTuples.Contains(Tuple.Create(x.PriceDate.Year, x.PriceDate.Month))).Select(x => x.Mtd);
Il metodo Where definisce nel mio contesto
public IEnumerable<T> Where(Expression<Func<T, bool>> predicate)
{
try
{
using (new TimedLogger(_perfLogger, GetCompletedText("Where")))
{
return Authorize(_repo.Where(predicate).ToList(), AuthAccessLevel.Read);
}
}
catch (Exception ex)
{
_logger.Error(ex);
throw;
}
}
EF6 non supporta (non può tradurre in SQL) i Tuple.Create
(e Tuple<>
), i join di raccolte in memoria, Contains
raccolte in memoria su tipi non primitivi e molti altri.
La soluzione nel tuo caso è quella di sostituire la coppia (int year, int month) con un'espressione di tipo primitivo come questa:
int period = 12 * year + (month - 1)
e utilizzarlo per filtrare, ad es
var periods = period.ToList() // gives you List<KeyValuePair<int, int[]>>
.SelectMany(kvp => kvp.Value, (year, month) => 12 * year + (month - 1));
e quindi all'interno della query LINQ
periods.Contains(12 * x.PriceDate.Year + (x.PriceDate.Month - 1))
Si noti che in LINQ to Entities i periods
query non devono essere HashSet<int>
(o List<int>
ecc.) - IEnumerable<int>
è sufficiente perché verrà valutato localmente una volta e convertito in SQL IN (val1, val2, ..., valN)
.