Entity Framework Core GroupBy Дата - PullRequest
3 голосов
/ 31 января 2020

В C# вы можете группировать по .Date:

db.History.GroupBy(x => x.Timestamp.Date)
          .Select(g => new { key = g.Key, aggregate = g.Count() })

Однако эквивалентный F # не работает:

db.History.GroupBy(fun x -> x.Timestamp.Date)
          .Select(fun g -> { Date = g.Key; Count = g.Count()} )

Соответствующая запись:

type DateCount = {
    Date: DateTime
    Count: int
}

Выдает следующую ошибку:

System.InvalidOperationException: не удалось перевести выражение LINQ 'DbSet<HistoryEntity> .GroupBy( source: h => copyOfStruct => copyOfStruct.Date.Invoke(h.Timestamp), keySelector: h => h)'. Либо переписать запрос в форме, которую можно перевести, либо явно переключиться на оценку клиента, вставив вызов либо AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsyn c ().

Как мне сгруппировать по дате?

Ответы [ 2 ]

4 голосов
/ 31 января 2020

Таким образом, в C#, когда вы используете LINQ-to- SQL запросов , вы используете методы расширения для IQueryable<T>. Если мы посмотрим на сигнатуру скажем, метод GroupBy , вы увидите, что сигнатура функции на самом деле

IQueryable<TSource>.GroupBy<TSource,TKey>(Expression<Func<TSource,TKey>> keySelector)

Что происходит? Expression<> - это специальный тип - когда компилятор C# обнаруживает тип Expression<>, компилятор создает AST и передает объект AST (типа Expression<Func<>>) вместо обычного делегата. Предполагается, что базовые функции будут проверять AST и создавать любое необходимое выражение запроса, например, SQL для запроса к базе данных.

Вы можете попробовать сами:

Expression<Func<int>> getRandom = () => 4; //random, chosen by fair dice roll

Вы можете проверьте свойства getRandom, чтобы увидеть AST. Поскольку magi c происходит в компиляторе C#, когда вы делаете это в F #, это не обрезает его.

To go более подробно, компилятор F # может распознавать Expression<>, но делает это, применяя неявную цитату F # - так вы получаете вызов метода с обёрткой цитаты F #, который преобразуется в дерево выражений C#. (Извините, если он был запущен.)

F # имеет собственный интерпретатор запросов строитель для SQL. Это позволяет вам писать выражения для вычислений, такие как seq, которые переводят в SQL запросы. Это работает так, как вы ожидаете.

query {
    for record in db do
    select record
}
1 голос
/ 31 января 2020

Группировка по .Date работает при использовании в выражении запроса.

query {
    for h in db.History do
    groupValBy h h.Timestamp.Date into g
    select {
        Date  = g.Key
        Count = g.Count()
    }
}

Код, украденный из здесь .

Если кто-то может объяснить, почему выражение запроса работает, но версия LINQ нет, я был бы признателен:)

...