dotnet / dotnet/efcore

Avoid generating discriminator for TPC query returning entities of a single leaf type

Open
#28,199 2 comments 0 reactions 0 assignees View on GitHub
area-query
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

This is the kind of query that TPC mapping is really good for, so it would be nice to have really clean generated SQL for it. Used latest daily build as of this morning, UK time.

Query:

```C#
var results3 = context.Animals.OfType().Where(a => a.Species.StartsWith("F")).ToList();
```

SQL:

```sql
SELECT [t].[Id], [t].[Species], [t].[Name], [t].[EducationLevel], [t].[Discriminator]
FROM (
SELECT [c].[Id], [c].[Species], [c].[Name], [c].[EducationLevel], N'Cat' AS [Discriminator]
FROM [Cats] AS [c]
) AS [t]
WHERE [t].[Species] LIKE N'F%'
```

Full repro:

```C#
public abstract class Animal
{
public int Id { get; set; }
public string Species { get; set; }
}

public class FarmAnimal : Animal
{
public decimal Value { get; set; }
}

public class Pet : Animal
{
public string Name { get; set; }
}

public class Cat : Pet
{
public string EducationLevel { get; set; }
}

public class Dog : Pet
{
public string FavoriteToy { get; set; }
}

public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(Your.ConnectionString)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();


public DbSet Animals { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasSequence("AnimalIds");

modelBuilder.Entity().UseTpcMappingStrategy().Property(e => e.Id).HasDefaultValueSql("NEXT VALUE FOR [AnimalIds]");
modelBuilder.Entity().ToTable("Pets");;
modelBuilder.Entity().ToTable("Cats");
modelBuilder.Entity().ToTable("Dogs");
modelBuilder.Entity().ToTable("FarmAnimals");

}
}

public class Program
{
public static void Main()
{
using (var context = new SomeDbContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();

context.AddRange(
new Cat {Name = "Alice", Species = "Felis catus", EducationLevel = "MBA"},
new Cat {Name = "Mac", Species = "Felis catus", EducationLevel = "BA"},
new Dog {Name = "Toast", Species = "Canis familiaris", FavoriteToy = "Mr. Squirrel"},
new FarmAnimal {Value = 100.0m, Species = "Ovis aries"});

context.SaveChanges();
}

using (var context = new SomeDbContext())
{
var results3 = context.Animals.OfType().Where(a => a.Species.StartsWith("F")).ToList();
}
}
}
```

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.