dotnet / dotnet/efcore

Consider improving model validation for when the derived type only has navigations and no discriminator

Open
#34,107 13 comments 0 reactions 0 assignees View on GitHub
area-change-tracking area-model-building customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

NET8. I will try to describe the issue as briefly as possible.

1) Nuget package **EntityConfig** contains _model-DB_ mappings;
2) Nuget package **Base** contains entity `TenantInner` and consumes **EntityConfig**: entity `TenantInner` is bound to table `TENANT`;
3) Solution **MySolution** consumes packages **EntityConfig** and **Base** and contains entity `Tenant` which inherits `TenantInner`. `Tenant` only contains navigation properties and naturally references the same table - `TENANT`.

The reason why I splitted `TenantInner` and `Tenant`: `TenantInner` is used in many solutions. `Tenant` contains several navigation properties - we do not want to pull them all into **Base**, since they are needed in **MySolution** only.

Problem: I cannot make this structure work, getting either "**A key cannot be configured on 'Tenant' because it is a derived type**" or "**ORA-00904: "C1"."DISCRIMINATOR": invalid identifier**" (this one happens when trying to construct EF query joining `DbSet` property in _DbContext_) exceptions, depending on the way I've tried to resolve the issue.

My latest setup (I don't think `TenantInner` structure is relevant here, so skipping):

============ EntityConfig Nuget package ===========================================
```
public class TenantEntityConfig : EntityConfigBase where TBase : TenantEntity
{
public TenantEntityConfig(Action> builder = null)
: base(builder)
{ }

public override void Configure(EntityTypeBuilder builder)
{
builder.ToTable("TENANT");
builder.HasKey(x => x.Id);
builder.Property(x => x.Id)
.HasColumnName("ID").IsRequired()
.ValueGeneratedNever();
builder.Property(x => x.ShortName)
.HasColumnName("NAME");
...
builder.Property(x => x.CompanyId)
.HasColumnName("COMPANY_ID").IsRequired();
...
base.Configure(builder);
}
}

public class TenantEntityConfig : TenantEntityConfig
{ }
```
============ MySolution ===========================================
```
public class Tenant : TenantInner
{
public Company Company { get; set; }
...
}

builder.ApplyConfiguration(new TenantEntityConfig());
builder.Entity(builder =>
{
builder.HasBaseType();
builder.HasOne(x => x.Company)
.WithMany()
.HasPrincipalKey(x => x.Id)
.HasForeignKey(x => x.CompanyId);
...
});
```

I don't understand why it should not work: as I see it, when `DbSet` is referenced - the EF should construct the query using `TENANT` table and its navigation properties tables (if included - `COMPANY` etc.). If `DbSet` is referenced (in **Base** package) - the same `TENANT` table should be used. However, I don't know how to let EF know that "discriminator" is not relevant here.

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.