A key cannot be configured on 'FooEntity' because it is a derived type. The key must be configured on the root type 'Foo'

Viewed 1973

I have a base class Foo, with all properties that I need across my application. The ui uses a derived class (FooUi) with the necessary ui properties. The database uses a derived class (FooEntity) with an Id property, for example. But that seems to be the crux of the matter, because according to the exception, this is probably not allowed in EF core. Is there an elegant solution here so that I don't have to pack the Id property in my base class, as I don't need it anywhere else and still got the possibility to have a key?

public class Foo
{

}

public class FooEntity : Foo
{
    public int Id { get; set; }
}

public class FooDbContext : DbContext
{
    public DbSet<FooEntity> Foos { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<FooEntity>(builder =>
        {
            builder.ToTable("Foos");

            // here the exception occurs
            builder.HasIndex(entity => entity.Id);
        });

        base.OnModelCreating(modelBuilder);
    }
}

Exception

A key cannot be configured on 'FooEntity' because it is a derived type. The key must be configured on the root type 'Foo'. If you did not intend for 'Foo' to be included in the model, ensure that it is not included in a DbSet property on your context, referenced in a configuration call to ModelBuilder, or referenced from a navigation property on a type that is included in the model.

1 Answers

I have answered a slightly similar question previously.

The main reason why I think you should avoid mixing your UI model (FooUi) and your data access model (FooEntity) is that you are violating the seperation of concerns design principle.

As you have seen Entity Framework doesn't support this and although I think it's mainly for technical reasons it's also an indicator that you are trying to do something you shouldn't. You have only given a very simplified and hypothetical example so it's a little difficult to give you a proper example of why it's a bad idea. But to borrow from my old answer (you can replace "domain" with "ui"):

When you are mixing domain models with data access models, you make your domain logic completely dependent on how you model the data in your database. This quickly limits your options because the database may have some restrictions on how you can model your data that doesn't fit well with the domain logic you want to implement as well as making maintenance difficult. E.g. if you decide to split up one DB table into two then you might have a big task ahead of you in order to make your domain logic work with those two new models/tables. Additionally, making performance optimizations in your database easily becomes a nightmare if not thought through ahead of time - and you shouldn't spend time thinking of optimizing your system before it's necessary.

In the comments you only mention cosmetic reasons for why you want to do this, such as "avoid duplicate code" and "I do not need an ID [...] in the UI" and that's a very small benefit compared to the downside of making your dependencies between models so convoluted.

What you should do instead: create a model separately for data access (entity model) and UI. In this case (just like your own scenario) you still need some code/logic to map data between the two models. The only downside to this is that you create two similar looking classes, which is really not time consuming to make at all.

Related