Невозможно создать постоянное значение типа 'System.Tuple - PullRequest
1 голос
/ 14 апреля 2019

Я пытаюсь реализовать выражение c # linq, которое позволит мне извлекать данные, основанные на годах и месяцах. Ошибка выдается в методе where моего контекста.

В настоящее время я получаю ошибку

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.'

Выражение 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);

Метод Where определяет в моем контексте

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;
            }
        }

Ответы [ 2 ]

1 голос
/ 24 апреля 2019

EF6 не поддерживает (не может преобразовать в SQL) Tuple.CreateTuple<> конструкторы), объединения коллекций в памяти, Contains коллекции в памяти для не примитивных типов и многие другие.

Решение в вашем случае состоит в замене пары (int year, int month) на выражение примитивного типа, например:

int period = 12 * year + (month - 1)

и использовать его для фильтрации, например

var periods = period.ToList() // gives you List<KeyValuePair<int, int[]>>
    .SelectMany(kvp => kvp.Value, (year, month) => 12 * year + (month - 1));

и затем внутри запроса LINQ

periods.Contains(12 * x.PriceDate.Year + (x.PriceDate.Month - 1))

Обратите внимание, что в запросе LINQ to Entities periods необязательно должно быть HashSet<int> (или List<int> и т. Д.) - достаточно IEnumerable<int>, поскольку он будет оценен локально один раз и преобразован в SQL IN (val1, val2, ..., valN) критерии.

1 голос
/ 15 апреля 2019

Попробуйте присоединиться?

            var benchmark1Returns = GetViewService<MV_INDEX_PERFORMANCE>()
                .Where(x => x.Mtd != null && x.IndexId == benchMark1)
                .Join(periodTuples,
                    b1r => new { x = b1r.PriceDate.Year, y = b1r.PriceDate.Month },
                    tuple => new { x = tuple.Item1, y = tuple.Item2 },
                    (b, t) => b.Mtd);
...