Keyless entity without a table - broken in 7.0
As per this thread, I have a keyless entity which is not mapped to a table or view:
public sealed class StringSplitResult
{
public string Value { get; set; } = string.Empty;
}
...
modelBuilder.Entity<StringSplitResult>().HasNoKey().ToTable(null, t => t.ExcludeFromMigrations());
This works perfectly in EF Core 6.0.
Immediately after upgrading to 7.0, when I try to add a migration, I get:
System.ArgumentNullException: Value cannot be null. (Parameter 'name')
at Microsoft.EntityFrameworkCore.Utilities.Check.NotNull[T](T value, String parameterName)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeBuilderExtensions.ToTable[TEntity](EntityTypeBuilder1 entityTypeBuilder, String name, String schema, Action1 buildAction)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeBuilderExtensions.ToTable[TEntity](EntityTypeBuilder1 entityTypeBuilder, String name, Action1 buildAction)
EF Core version: 7.0.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6.0 Operating system: Windows 11 22H2 IDE: Visual Studio 2022 17.4
To work around this, I had to change the configuration to:
.ToTable(t => t.ExcludeFromMigrations())
I then had to modify the model snapshot and the designer for every existing migration to change:
b.ToTable((string)null, t => t.ExcludeFromMigrations());
to:
b.ToTable(t => t.ExcludeFromMigrations());
However, I have no idea whether this is the correct approach, or what side-effects this change will have.
This is an unfortunate side effect of dotnet/efcore#19811.
To achieve the same effect of .ToTable((string)null, t => t.ExcludeFromMigrations()); a migration needs to be created (or existing one modified) with .ToTable(t => t.ExcludeFromMigrations()); then call .ToTable((string)null); and create another migration.
We'll need to document this as a breaking change
@AndriySvyryd Thanks for the reply. How would I fix it for existing migrations? Is it enough to edit them to remove the (string)null parameter? And would there be any side-effects of not having the .ToTable((string)null) call?
Calling .ToTable(t => t.ExcludeFromMigrations()) instead of .ToTable((string)null) means that migrations will ignore it, but if you query the entity type then it will try to query the default table unless you have some configuration that overrides it (e.g. ToView). Also, if there are derived types in the model some validation could fail if the configuration is not compatible with the default table.
@AndriySvyryd For this specific entity, it's a private nested and sealed class used to represent the results of a STRING_SPLIT call, and it's only every queried with a .FromSqlInterpolated call, so hopefully that shouldn't be a problem.
Note from triage: document this as a breaking change.