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

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

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

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

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

 public IEnumerable GetResultsFromTable(string tableName) { using (var context = new WorkdataEntities()) { var table = context.CreateQuery("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"但它没有帮助。

有没有前进的方法,或者我必须在没有entity framework的帮助下完成这项工作?

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

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

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

 public IEnumerable GetResultsFromTable(string tableName) { using (var context = new WorkdataEntities()) { var query = context.ExecuteStoreQuery("SELECT " + "ALL_THOSE_COLUMN_NAMES... " + "FROM " + tableName; return query.ToList(); } } 

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

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

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

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

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

试试这个; 🙂

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