GroupBy в EF Core 3.1 не работает, даже для самого простого примера - PullRequest
5 голосов
/ 20 января 2020

Я обновляю проект EF6.x до EF Core 3.1. Решил go вернуться к основам и последовать примеру того, как снова установить отношения с нуля.

Согласно официальной документации Microsoft, Примеры базовых отношений EF , я перевел примеры в консольное приложение ниже:

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogPostsExample
{
    class Program
    {
        async static Task Main(string[] args)
        {
            // SQL Running in a Docker container - update as required
            var conString = "data source=localhost,14330;initial catalog=BlogsDb;persist security info=True;user id=sa;password=<Your super secure SA password>;MultipleActiveResultSets=True;App=EntityFramework;";

            var ctx = new MyContext(conString);

            await ctx.Database.EnsureCreatedAsync();

            var result = await ctx.Posts.GroupBy(p => p.Blog).ToArrayAsync();

        }
    }

    class MyContext : DbContext
    {
        private readonly string _connectionString;

        public MyContext(string connectionString)
        {
            _connectionString = connectionString;
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder
                .UseSqlServer(_connectionString);
            }
        }
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogId) //Tried with and without these keys defined.
            .HasPrincipalKey(b => b.BlogId);
        }

    }
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}

В БД нет данных. EF Core не может преобразовать

ctx.Posts.GroupBy(p => p.Blog)  

в запрос магазина. Мне кажется, это самый простой пример GroupBy, который вы можете попробовать.

Когда вы запускаете этот код, вы получаете следующее исключение:

System.InvalidOperationException: 'The LINQ expression 'DbSet<Post>
    .Join(
        outer: DbSet<Blog>, 
        inner: p => EF.Property<Nullable<int>>(p, "BlogId"), 
        outerKeySelector: b => EF.Property<Nullable<int>>(b, "BlogId"), 
        innerKeySelector: (o, i) => new TransparentIdentifier<Post, Blog>(
            Outer = o, 
            Inner = i
        ))
    .GroupBy(
        source: p => p.Inner, 
        keySelector: p => p.Outer)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'

Единственный способ заставить это работать это добавить что-то вроде AsEnumerable () перед GroupBy.

Это явно не очень хорошо с точки зрения производительности, это превращает группу за операцией в операцию на стороне клиента, где вы действительно хотите делать группировка на стороне сервера.

Я что-то упустил очевидное? Я изо всех сил пытаюсь поверить, что EF Core не может сделать самую простую группу из того, что EF Framework делает с первого дня. Это кажется фундаментальным требованием любого приложения, управляемого данными? (Или любое приложение с небольшим объемом данных!)

...