Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve exception message for TPC + Owned Entities Configuration #32870

Open
PHILLIPS71 opened this issue Jan 19, 2024 · 4 comments
Open

Improve exception message for TPC + Owned Entities Configuration #32870

PHILLIPS71 opened this issue Jan 19, 2024 · 4 comments

Comments

@PHILLIPS71
Copy link

PHILLIPS71 commented Jan 19, 2024

I've been attempting to use the TPC strategy where a owned entity is configured on the base entity, but I cannot get the migrations to generate the owned entity properties on the derived entities.

I've instead needed to move the OwnsOne configuration to each derived entity (FileSystemDirectory, FileSystemFile) to get the migration to include the PathInfo properties. If I do that however, I cannot filter or sort on the base entity as the LINQ expression cannot be translated.

It's something I've been banging my head against a wall at for some time now, as being able to sort and filter on the base class is important, but it cannot be done inside the generated SQL statement as the following fails.

await database
    .Entries
    .OrderBy(x => x.PathInfo.Name)
    .ToListAsync();

I'd ideally want to setup the entities and configuration like below, but it doesn't seem to be supported when the OwnsOne is configured on the base class.

public abstract class FileSystemEntry
{
    public int Id { get; set; }

    public PathInfo PathInfo { get; set; }

    public FileSystemDirectory? ParentDirectory { get; set; }
}

public class FileSystemDirectory : FileSystemEntry
{
}

public class FileSystemFile : FileSystemEntry
{
    public long Size { get; set; }
}

public class PathInfo
{
    public string Name { get; init; }

    public string FullName { get; init; }

    public string Extension { get; init; }

    public string DirectoryPath { get; init; }
}

public class FileSystemEntryConfiguration : IEntityTypeConfiguration<FileSystemEntry>
{
    public void Configure(EntityTypeBuilder<FileSystemEntry> builder)
    {
        builder
            .UseTpcMappingStrategy();

        builder
            .OwnsOne<PathInfo>(p => p.PathInfo);
    }
}

Does this issue relate to #9630? Or is something missing or being configured incorrectly here?

@ajcvickers
Copy link
Member

ajcvickers commented Jan 22, 2024

@AndriySvyryd Is this a duplicate of #32028? We currently throw:

The entity type 'FileSystemEntry' is not mapped, so by default the owned type 'PathInfo.PathInfo' will also be
unmapped. If this is intended explicitly map the owned type to 'null', otherwise map it to a named 'Table'.

This doesn't seem very clear, since 'FileSystemEntry' is mapped to a table.

Code:

using (var context = new SomeDbContext())
{
    await context.Database.EnsureDeletedAsync();
    await context.Database.EnsureCreatedAsync();
}

public class SomeDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(@"Data Source=localhost;Database=One;Integrated Security=True;TrustServerCertificate=true")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<FileSystemEntry>().OwnsOne(e => e.PathInfo);
        modelBuilder.Entity<FileSystemEntry>().UseTpcMappingStrategy();
        modelBuilder.Entity<FileSystemDirectory>();
        modelBuilder.Entity<FileSystemFile>();
    }
}

public abstract class FileSystemEntry
{
    public int Id { get; set; }
    public PathInfo PathInfo { get; set; }
    public FileSystemDirectory? ParentDirectory { get; set; }
}

public class FileSystemDirectory : FileSystemEntry
{
}

public class FileSystemFile : FileSystemEntry
{
    public long Size { get; set; }
}

public class PathInfo
{
    public string Name { get; init; }
    public string FullName { get; init; }
    public string Extension { get; init; }
    public string DirectoryPath { get; init; }
}

@AndriySvyryd
Copy link
Member

@AndriySvyryd Is this a duplicate of #32028?

Yes

This doesn't seem very clear, since 'FileSystemEntry' is mapped to a table.

It's an abstract type in TPC, so we don't map it to any table.

@ajcvickers ajcvickers changed the title TPC + Owned Entities Configuration Improve exception message for TPC + Owned Entities Configuration Jan 25, 2024
@ajcvickers ajcvickers added this to the Backlog milestone Jan 25, 2024
@PHILLIPS71
Copy link
Author

@ajcvickers is sorting or filtering on a owned type via the base abstract type something that's supported, or going to be supported at some point?

I've got the owned types configured on each derived entity, but the linq expression cannot be translated when querying on the base type.

The below query fails:

await database
    .Entries
    .OrderBy(x => x.PathInfo.Name)
    .ToListAsync();

@ajcvickers
Copy link
Member

@PHILLIPS71 That is tracked by #32028.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants