entity-framework - 在运行时更改表名

标签 entity-framework entity-framework-6

假设我有一个名为 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/

相关文章:

c# - 在 Entity Framework 中删除多对多集合的问题

c# - IRepository 和工作单元与预加载

c# - EF 枚举所有被忽略的属性

c# - LINQ 中的 LEFT JOIN 到实体?

.net - Entity Framework 连接字符串可以重用现有的连接字符串吗?

c# - Entity Framework 代码优先迁移 - 无法删除约束,因为它不存在(从 4.3 到 5.0 的命名约定)

c# - 服务器错误 "Method not found: ' 无效 System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior( bool 值 )'."

c# - 不同 DbContext 和不同模式之间的 Entity Framework 关系

c# - 单元测试 EF 的状态管理代码

c# - 在 LINQ 查询中调用 SQL Server UDF