使用Entity Framework实现动态表名

18

我有很多表格,它们具有相同的模型结构,但具有其他表格名称和其他数据(在这种情况下将是约100个表格)。 我想使用Entity Framework在运行时动态切换表格名称(例如从路由获取表格名称)。 数据库中的表格会被其他脚本动态添加和删除。 有没有一种像这样具有良好性能的方法来实现这一点?

db.Table("TableName")<SpecificModel>.Where(x => x.ID == ID)

2
我不禁想知道为什么你不把你的表格规范化成一个表格呢?如果它们都具有相同的结构... - Nathan A
最简单的方法就是规范化,但在这个项目中我无法这样做。需要将表格分开。 - Obin
为了实现您想要的功能,您需要使用新创建表的元数据更新edmx文件。我不知道有没有办法在运行时完成这个操作,因为更新edmx文件需要重新生成代码。我认为Entity Framework目前不支持您尝试做的事情。 - tdbeckett
你能给我们举一个创建表的例子吗?每个表之间的数据是否发生了根本性的变化?每个表格的意义是什么,即每个表格代表什么? - tdbeckett
表结构与模型相同(先前称为“SpecificModel”),每个表都是如此。它们在表名(如“Company_A”,“Company_B”,“Company_C”)和表中的数据方面有所不同,但结构相同。当然,我可以在此处粘贴所有模型及其 SQL 脚本以生成表(从 EF Code First 抓取),但我认为这并不必要,而且可能会混淆我的问题所在。 - Obin
我建议您创建另一个名为“ Company”的表格,其中包含公司名称和一个ID,并在 SpecificModel 表格中创建对 Company 表格的外键。然后,创建表格的脚本可以将数据插入具有公司ID的 SpecificModel 表格。这样,您就可以轻松使用linq来提取公司信息。 - tdbeckett
4个回答

7

你想像这样做吗?

foreach (string tableName in new[] { "Table1", "Table2" })
{
   var result = dbContext.Database.SqlQuery<SpecificModel>(string.Format("SELECT * FROM {0} WHERE ID=@p0", tableName), 1).FirstOrDefault();
}

1
它的工作很好,但仍然是查询。有没有用LINQ实现这个的方法? - Obin
是的,我认为我们可以使用反射和表达式在LINQ中实现这一点,但是一旦我弄清楚了,可能会有些复杂。在实体框架中,最终linq表达式将转换为SQL查询,因此不再有区别。使用这种方法,EF还将映射您的数据到类对象(SpecificModel)中,对吧 :) - Palanikumar
3
这将允许 SQL 注入攻击。 - tdbeckett
这不会起作用。因为表是动态创建的,EF不会知道返回类型的SpecificModel。 - tdbeckett
@tdbeckett,如果无法通过Linq实现需求,则必须使用此方法,并且我们需要正确验证输入字符串以避免SQL注入。 - Palanikumar
@tdbeckett,在问题中他提到:“我有许多具有相同模型结构的表”,并在评论中回复了您:“它们的区别在于表名,例如“Company_A”、“Company_B”、“Company_C”,以及这些表中的数据但不包括结构”。因此,我们可以使用SpecificModel类进行映射。 - Palanikumar

5

你知道这个程序处理不同表格的能力如何,除了名称不同之外? - Trevortni
我相信这是正确的链接: https://nodogmablog.bryanhogan.net/2013/08/entity-framework-in-an-dynamics-nav-navision-environment-or-using-ef-to-access-tables-with-unknown-table-names/ - Tausif

2
你可以这样做:
        // Gets entity type from specified namespace/assembly
        Type entityType = Type.GetType(string.Format("Your.NameSpace.{0},{1}", entityName, "Assembly.Name"));
        // Finds item to update based on its primary key value
        var entity = _dbContext.Find(entityType, entityKey);
        // Finds column to update preference for
        PropertyInfo propertyInfo = entity.GetType().GetProperty(entityField);
        // Set and update (date example given)
        propertyInfo.SetValue(entity, isOptIn ? (DateTime?)null : (DateTimeOffset?)DateTime.Now, null);
        _dbContext.SaveChanges();

0
如果您决定从动态表名中选择数据,那么您将无法设置查询的类型。
因此,在这里我们尝试一些反向代码,从模型命名空间中查找表名类型。
然后使用这个表设置上下文,如果需要,还可以使用where条件。
var tableName = item.TableName;
    Type entityType = Type.GetType(string.Format("AlbashaSweets.Models.{0}", tableName));
    var data = _DBContext.Set(entityType);
    
    //AlbashaSweets.Models is Your Namespace 

请阅读如何撰写好的答案?。虽然这个代码块可能回答了OP的问题,但如果您解释一下这段代码与问题中的代码有何不同,您做出了哪些更改,为什么要更改以及为什么这样解决问题而不引入其他问题,那么这个答案将会更加有用。- 来自评论 - Saeed Zhiany

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接