Jeżeli dobrze rozumiem to problemem nie jest to zapytanie?
var filtered = _applicationDbContext.FormAssocciates
.Include(x => x.ApplicationUser)
.Include(x => x.Form).ThenInclude(x => x.ApplicationUser)
.GroupBy(x => x.FormId)
.Select(x => x.First().Form);
ale zapytanie które wyglądałoby tak:
var filtered = _applicationDbContext.FormAssocciates
.Include(x => x.ApplicationUser)
.Include(x => x.Form).ThenInclude(x => x.ApplicationUser)
.GroupBy(x => x.FormId)
.Select(x => x.First().Form)
.OrderBy( ... )
.Skip( ... )
.Take( ... );
Bo próbując takie zapytanie dostaję wyjątek:
The LINQ expression 'DbSet<FormAssocciates>()
.GroupBy(f => f.FormId)
.Select(g => g
.AsQueryable()
.LeftJoin(
inner: DbSet<Form>(),
outerKeySelector: e => EF.Property<int?>(e, "FormId"),
innerKeySelector: f0 => EF.Property<int?>(f0, "Id"),
resultSelector: (o, i) => new TransparentIdentifier<FormAssocciates, Form>(
Outer = o,
Inner = i
))
.LeftJoin(
inner: DbSet<ApplicationUser>(),
outerKeySelector: e => EF.Property<int?>(e.Inner, "ApplicationUserId"),
innerKeySelector: a => EF.Property<int?>(a, "Id"),
resultSelector: (o, i) => new TransparentIdentifier<TransparentIdentifier<FormAssocciates, Form>, ApplicationUser>(
Outer = o,
Inner = i
))
.Select(e => IncludeExpression(
EntityExpression:
e.Outer.Inner,
NavigationExpression:
e.Inner, ApplicationUser)
)
.First())
.OrderBy(e0 => e0.Name)' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Testowy kod:
using EFCorePractice.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
optionsBuilder.UseSqlite("Data Source=database.db");
using var context = new AppDbContext(optionsBuilder.Options);
string queryWithoutOrderBy = context.FormAssocciates
.Include(x => x.ApplicationUser)
.Include(x => x.Form).ThenInclude(x => x.ApplicationUser)
.GroupBy(x => x.FormId)
.Select(x => x.First().Form)
.ToQueryString();
Console.WriteLine(queryWithoutOrderBy);
//To się wywala:
string secondQuery = context.FormAssocciates
.Include(x => x.ApplicationUser)
.Include(x => x.Form).ThenInclude(x => x.ApplicationUser)
.GroupBy(x => x.FormId)
.Select(x => x.First().Form)
.OrderBy(x => x.Name)
.Skip(20)
.Take(10).ToQueryString();
Console.WriteLine(secondQuery);
public class FormAssocciates
{
public int Id { get; set; }
public string Name { get; set; } = default!;
public int? FormId { get; set; }
public Form? Form { get; set; }
public int? ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
public class Form
{
public int Id { get; set; }
public string Name { get; set; } = default!;
public int? ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser
{
public int Id { get; set; }
public string Firstname { get; set; } = default!;
public string Surname { get; set; } = default!;
}
public class AppDbContext : DbContext
{
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Form> Forms { get; set; }
public DbSet<FormAssocciates> FormAssocciates { get; set; }
public AppDbContext(DbContextOptions options)
: base(options)
{
}
}
Jedna rzecz mnie zastanawiam bo masz:
context.FormAssocciates
ale potrzebujesz tak naprawdę Form:
.Select(x => x.First().Form)
Może dałoby się skonstruować inaczej to zapytanie, możesz opisać co ono powinno pobrać? Może gdyby zaczynało się od:
context.Form
byłoby łatwiej?
Bo dla zapytania:
string queryWithoutOrderBy = context.FormAssocciates
.Include(x => x.ApplicationUser)
.Include(x => x.Form).ThenInclude(x => x.ApplicationUser)
.GroupBy(x => x.FormId)
.Select(x => x.First().Form)
.ToQueryString();
dostaję takiego sql a możliwe że dałoby się to uprościć
SELECT "t0"."Id", "t0"."ApplicationUserId", "t0"."Name", "t0"."Id0", "t0"."Firstname", "t0"."Surname"
FROM (
SELECT "f"."FormId"
FROM "FormAssocciates" AS "f"
GROUP BY "f"."FormId"
) AS "t"
LEFT JOIN (
SELECT "t1"."Id", "t1"."ApplicationUserId", "t1"."Name", "t1"."Id0", "t1"."Firstname", "t1"."Surname", "t1"."FormId"
FROM (
SELECT "f1"."Id", "f1"."ApplicationUserId", "f1"."Name", "a"."Id" AS "Id0", "a"."Firstname", "a"."Surname", "f0"."FormId", ROW_NUMBER() OVER(PARTITION BY "f0"."FormId" ORDER BY "f0"."Id", "f1"."Id", "a"."Id") AS "row"
FROM "FormAssocciates" AS "f0"
LEFT JOIN "Forms" AS "f1" ON "f0"."FormId" = "f1"."Id"
LEFT JOIN "ApplicationUsers" AS "a" ON "f1"."ApplicationUserId" = "a"."Id"
) AS "t1"
WHERE "t1"."row" <= 1
) AS "t0" ON "t"."FormId" = "t0"."FormId"