Я обновляю проект 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 делает с первого дня. Это кажется фундаментальным требованием любого приложения, управляемого данными? (Или любое приложение с небольшим объемом данных!)