-
-
Notifications
You must be signed in to change notification settings - Fork 787
Open
Milestone
Description
Product
Hot Chocolate
Version
15.0.3
Link to minimal reproduction
https://github.com/cenx1/HC15AbstractInheritanceProblem
Steps to reproduce
Use entities that inherit from an abstract class:
[InterfaceType]
public abstract class FarmAnimal
{
public int Id { get; set; }
public int FarmerId { get; set; }
public virtual Farmer FarmerOwner { get; set; } = default!;
}
public class Cow : FarmAnimal
{
public double AmountOfMilk { get; set; }
}
public class Pig : FarmAnimal
{
public double AmountOfMeat { get; set; }
}
public class Cat : FarmAnimal
{
public int Age { get; set; }
}
public class Farmer
{
public int Id { get; set; }
public string Name { get; set; } = default!;
public virtual ICollection<FarmAnimal> FarmAnimals { get; set; } = [];
}
Use DbContext for the entities:
public class AnimalContext : DbContext
{
public virtual DbSet<FarmAnimal> FarmAnimals { get; set; }
public virtual DbSet<Farmer> Farmers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FarmAnimal>(entity => { entity.UseTpcMappingStrategy(); });
modelBuilder.Entity<Cow>(entity => { entity.ToTable("Cow"); });
modelBuilder.Entity<Pig>(entity => { entity.ToTable("Pig"); });
modelBuilder.Entity<Cat>(entity => { entity.ToTable("Cat"); });
}
}
Create a dataloader that uses QueryContext that fetches a collection of entities that inherits from an abstract class:
[DataLoader]
public static async Task<Dictionary<int, Page<FarmAnimal>>> GetFarmAnimalsByFarmerIdAsync(
IReadOnlyList<int> farmerIds,
QueryContext<FarmAnimal> queryContext,
PagingArguments pagingArgs,
AnimalContext context,
CancellationToken cancellationToken
)
{
var result = await context.FarmAnimals
.Where(fa => farmerIds.Contains(fa.FarmerId))
.OrderBy(fa => fa.Id)
.With(queryContext) // I believe this is the culprit
.ToBatchPageAsync(x => x.FarmerId, pagingArgs, cancellationToken);
return result;
}
Execute a query that queries farm animals on farmer:
query a {
farmer {
id
name
farmAnimals(pagingArguments: { first: 3 }) {
id
__typename
... on Cat {
age
}
... on Cow {
amountOfMilk
}
... on Pig {
amountOfMeat
}
}
}
}
What is expected?
The response returns something like:
{
"data": {
"farmer": {
"id": "RmFybWVyOjE=",
"name": "John Doe",
"farmAnimals": {
"edges": [
{
"node": {
"id": 1,
"__typename": "Cow",
"amountOfMilk": 10
}
},
{
"node": {
"id": 2,
"__typename": "Pig",
"amountOfMeat": 5
}
},
{
"node": {
"id": 3,
"__typename": "Cat",
"age": 3
}
}
]
}
}
}
}
What is actually happening?
Response:
{
"errors": [
{
"message": "Unexpected Execution Error",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"farmer",
"farmAnimals"
],
"extensions": {
"message": "The LINQ expression 'DbSet<FarmAnimal>()\r\n .Where(f => __farmerIds_0\r\n .Contains(f.FarmerId))\r\n .GroupBy(f => (f is Cow) ? (FarmAnimal)(FarmAnimal)new Cow{ \r\n Id = ((Cow)f).Id, \r\n AmountOfMilk = ((Cow)f).AmountOfMilk, \r\n FarmerId = f.FarmerId \r\n }\r\n : (f is Pig) ? (FarmAnimal)(FarmAnimal)new Pig{ \r\n Id = ((Pig)f).Id, \r\n AmountOfMeat = ((Pig)f).AmountOfMeat, \r\n FarmerId = f.FarmerId \r\n }\r\n : (f is Cat) ? (FarmAnimal)(FarmAnimal)new Cat{ \r\n Id = ((Cat)f).Id, \r\n Age = ((Cat)f).Age, \r\n FarmerId = f.FarmerId \r\n }\r\n : null.FarmerId)' 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.",
}
}
],
"data": {
"farmer": {
"id": "RmFybWVyOjE=",
"name": "John Doe",
"farmAnimals": null
}
}
}
Relevant log output
Additional context
No response
Hanskrogh