使用Entity Framework从动态创建的表中查询数据

时间:2012-01-17 15:00:55

标签: c# sql entity-framework

TLDR;当在编译时不知道表名时,如何使用Entity Framework从表中读取数据?

有一个外部系统处理大量信息,然后为每个批处理运行创建一个新表,并将一些数据存储在该表中。这些新表的列布局是事先已知的,因此我从现有数据库生成了一个ADO.NET实体数据模型(edmx文件),其中有一个表具有完全相同的列布局。

该数据库中的原始表名为ResultTableTemplate,因此表示该表的实体类也称为ResultTableTemplate

我试图弄清楚如何使用我的ADO.NET实体数据模型从这些动态创建的表中读取并返回IEnumerable<ResultTableTemplate>。到目前为止我所做的是:

public IEnumerable<ResultTableTemplate> GetResultsFromTable(string tableName) {
    using (var context = new WorkdataEntities()) {
        var table = context.CreateQuery<ResultTableTemplate>("SELECT " +
            "ALL_THOSE_COLUMN_NAMES... " +
            "FROM " + tableName;

        var query = from item in table select item;

        return query.ToList();
    }
}

当我运行查询时,我得到一个System.Data.EntitySqlException,其中包含以下消息:

  

'ResultTable419828'无法在当前范围内解析或   上下文。确保所有引用的变量都在范围内   加载了所需的模式,并引用了名称空间   正确。近成员访问表达式,第1行,第225列。

ResultTable419828tableName

的值

我尝试了tableName + " AS ResultTableTemplate",但没有帮助。

我有没有前进的方法,或者在没有实体框架的帮助下我是否必须这样做?

编辑:我现在意识到我写的查询文本并没有一直传递到底层SQL Server实例,而是由实体框架解释,返回ObjectQuery<ResultTableTemplate>实例,因此它在Context的自动生成的ResultTable419828实例中查找DbSet

不过,有没有办法让我做到我需要做的事情?

编辑:感谢Ladislav Mrnka。现在,我这样做:

public IEnumerable<ResultTableTemplate> GetResultsFromTable(string tableName) {
    using (var context = new WorkdataEntities()) {
        var query = context.ExecuteStoreQuery<ResultTableTemplate>("SELECT " +
            "ALL_THOSE_COLUMN_NAMES... " +
            "FROM " + tableName;

        return query.ToList();
    }
}

2 个答案:

答案 0 :(得分:11)

这不是直接可能的。将实体映射到ResultTableTemplate时,您需要对该实体的表名进行硬编码。实体只能映射一次(每个模型),因此在运行时,此实体的每个EF查询始终会导致查询ResultTableTemplate表。

改变的唯一方法是行为是在运行时修改映射文件(SSDL),这是非常难看的黑客,因为它要求您更改XML文件并重新加载它。每次更改文件时都必须手动构建MetadataWorkspace。构建MetadataWorkspace是EF中性能最高的操作之一。在正常运行中,每个应用程序运行只创建一次MetadataWorkspace

有简单的解决方法。你知道表名,你知道表结构 - 它是固定的。因此,使用直接SQL并使用EF将结果具体化到映射的实体类中:

var table = context.ExecuteStoreQuery<ResultTableTemplate>("SELECT ... FROM " + tableName);

缺点是你不能在这种方法中使用Linq,但你的要求不太适合EF。

答案 1 :(得分:0)

试试这个; :)

string tableName = "MyTableTest";

// Fetch the table records dynamically
var tableData = ctx.GetType()
                .GetProperty(tableName)
                .GetValue(ctx, null);