假设我有一个名为 Employee 的 db 表和一个相应的 EF 6.0 db-first 模型。
获取表 Employee 的所有行是通过查询完成的:context.Employees.ToList()
是否可以在运行时和按需将数据库表名重定向到 Test1,同时使用相同的对象名和查询?
也许是 EF 6.0 拦截器使用的案例?
最佳答案
我知道距离原始帖子已经有一段时间了,但我会添加我的答案以帮助其他人。我有具有不同表名的通用 SQL 队列表。 IE。两个表的架构完全相同。我创建了一个框架,以便您可以通过提供名称来动态轮询您选择的表,这就是我需要在运行时更新表名称的原因。基本上,您可以创建一个拦截器来拦截来自 Entity Framework 的原始 SQL 查询并从那里更新表名。
public class MyInterceptor : IDbCommandInterceptor
{
private const string TableReplaceString = "[TheTableNameToReplace]";
private void ReplaceTableName(DbCommand command, IEnumerable<DbContext> contexts)
{
var myContext = contexts?.FirstOrDefault(x => x is MyContext) as MyContext;
if (myContext != null && command != null && command.CommandText.Contains(TableReplaceString))
{
command.CommandText = command.CommandText.Replace(TableReplaceString, $"[{myContext.NewTableName}]");
}
}
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
ReplaceTableName(command, interceptionContext.DbContexts);
}
}
当然,您必须从某个地方获取新表名。从构造函数或自定义 DBContext 中存储的字段,您可以从interceptionContext.DbContexts 中获取。
然后你只需要为你的上下文注册拦截器。
public class MyContext : DBContext
{
public readonly string NewTableName;
public MyContext(string connectionString, string newTableName)
: base(connectionString)
{
NewTableName = newTableName;
// Set interceptor
DbInterception.Add(new MyInterceptor());
}
}
更新:
我发现如果在上面的构造函数中添加拦截器会导致内存泄漏。 DotMemory 不会告诉你这个。确保在静态构造函数中添加拦截器。
public class MyContext : DBContext
{
public readonly string NewTableName;
static MyContext()
{
// Set interceptor only in static constructor
DbInterception.Add(new MyInterceptor());
}
public MyContext(string connectionString, string newTableName)
: base(connectionString)
{
NewTableName = newTableName;
}
}
关于entity-framework - 在运行时更改表名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27259949/