There is a trick which I used to get multiple entities to map to one table.
First your entities must derive from a common type. This base type itself will not be part of your context.
Give the context a fake table name, which can be parsed to get the original table name. I used the table name format: $$$TableName$$$
. It can have 3 or more $.
Then intercept the command and replace the command text.
The hierarchy:
class MyEntityBase
{
// Common properties here
}
[Table("MyTable")]
class MyEntityV1 : MyEntityBase
{
}
[Table("$$$MyTable$$$")]
class MyEntityV2 : MyEntityBase
{
}
The interceptor:
class EntityNameReplacerInterceptor: DbCommandInterceptor
{
private static Regex regex = new Regex("([\\$]{3,})(.+)\\1", RegexOptions.Compiled);
public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
{
ManipulateCommand(command);
return base.ReaderExecuting(command, eventData, result);
}
public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)
{
ManipulateCommand(command);
return base.NonQueryExecuting(command, eventData, result);
}
public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
ManipulateCommand(command);
return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);
}
public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)
{
ManipulateCommand(command);
return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
}
public override InterceptionResult<object> ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<object> result)
{
ManipulateCommand(command);
return base.ScalarExecuting(command, eventData, result);
}
public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result, CancellationToken cancellationToken = default)
{
ManipulateCommand(command);
return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);
}
private void ManipulateCommand(DbCommand result)
{
result.CommandText = regex.Replace(result.CommandText, "$2");
}
}
Configuring The DbContext
:
DbSet<MyEntityV1> V1s { get; set; }
DbSet<MyEntityV2> V2s { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new EntityNameReplacerInterceptor());
}