dotnet / dotnet/efcore

EF8 core: filtering by enum doesn't work with TPH and OfType

Open
#32,865 2 comments 1 reaction 1 assignee Claimed by @AndriySvyryd View on GitHub
area-query customer-reported regression
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

### Code

context.Technologies has TPH, discriminator is based on TechnologyType enum (8 different values)

```C#
public static class ContextExtensions
{
public static IQueryable StorageTechnologiesQuery(this AppDbContext context) =>
context.Technologies
.Include(x => x.Manufacturer)
.Where(x => (x.TechnologyType == TechnologyType.StorageA
|| x.TechnologyType == TechnologyType.StorageB
|| x.TechnologyType == TechnologyType.StorageC
|| x.TechnologyType == TechnologyType.StorageD));

public static IQueryable StorageTechnologyWithDetailsQuery(this AppDbContext context) =>
StorageTechnologiesQuery(context)
.Include(x => ((StorageATechnologyDto)x).SomeDetailsX)
.Include(x => ((StorageATechnologyDto)x).SomeDetailsY)
.Include(x => ((StorageATechnologyDto)x).SomeDetailsZ)
.Include(x => ((StorageCTechnologyDto)x).SomeDetailsX)
.Include(x => ((StorageCTechnologyDto)x).SomeDetailsY)
.Include(x => ((StorageCTechnologyDto)x).SomeDetailsZ)
.Include(x => ((StorageDTechnologyDto)x).SomeDetailsY)
.ThenInclude(x => x.AssociatedData)
.ThenInclude(x => x.Manufacturer)
.Include(x => ((StorageDTechnologyDto)x).SomeDetailsX)
.Include(x => ((StorageDTechnologyDto)x).SomeDetailsZ)
.Include(x => ((StorageDTechnologyDto)x).SomeDetailsX)
.Include(x => ((StorageDTechnologyDto)x).SomeDetailsY);
}
```

Case:

```C#
var entity = await _context.StorageTechnologyWithDetailsQuery()
.OfType()
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
```

### Include verbose output

.NET 8 & EF core 8.0.1 produces WHERE 0 = 1

```
SELECT TOP(1) [t].[Id], [t].[CreatedAt], [t].[CreatedBy], [t].[Description], ...other columns
FROM [Technologies] AS [t]
INNER JOIN [Manufacturers] AS [m] ON [t].[ManufacturerId] = [m].[Id]
LEFT JOIN [StorageDTechnologySomeDetailsY] AS [t0] ON [t].[Id] = [t0].[TechnologyId]
LEFT JOIN [StorageDTechnologySomeDetailsX] AS [t1] ON [t].[Id] = [t1].[TechnologyId]
WHERE 0 = 1
```

It worked in .NET 7 & EF7

### Workaround

Replace

```C#
.Where(x => (x.TechnologyType == TechnologyType.StorageA
|| x.TechnologyType == TechnologyType.StorageB
|| x.TechnologyType == TechnologyType.StorageC
|| x.TechnologyType == TechnologyType.StorageD));
```

by

```C#
.Where(x => (x is StorageATechnologyDto
|| x is StorageBTechnologyDto
|| x is StorageCTechnologyDto
|| x is StorageDTechnologyDto));
```

### Include provider and version information

EF Core version: core 8.0.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 8.0
Operating system: Windows & Linux
IDE: Visual Studio 2022 17.8.4

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.