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列。
ResultTable419828
是tableName
我尝试了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();
}
}
答案 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);