【问题标题】:Querying data using Entity Framework from dynamically created table使用实体框架从动态创建的表中查询数据
【发布时间】:2012-01-17 15:00:55
【问题描述】:

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&lt;ResultTableTemplate&gt; 实例的实体框架解释,因此它会在自动生成的 DbSet Context 实例中查找 ResultTable419828

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

编辑:谢谢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();
    }
}

【问题讨论】:

  • 我认为这是创建 EntityQuery,而不是数据库查询。因此 FROM 是 DbSet 而不是数据库表。
  • CreateQuery&lt;T&gt;() 返回一个ObjectQuery&lt;T&gt; - 我现在看到你是正确的。查询不是针对数据库表,而是针对 DbSet。你认为有办法做我需要做的吗?
  • 我们使用带有 SqlQuery 的 DbConnection 从数据库中获取标量值。我没有编写 DAL 的那部分,所以我不完全确定它是如何工作的,但你也许可以从那里开始。
  • you were close....使用context.ExecuteStoreQuery而不是context.CreateQuery,因为它是一个SQL表达式,EF可以在上下文的数据库上执行查询,并且可以选择返回一个类型化的结果集如果结构相同。

标签: c# sql entity-framework


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

    试试这个; :)

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

    【讨论】:

    • 您能演示一下如何查询该表吗?
    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2015-06-16
    相关资源
    最近更新 更多