【问题标题】:How to process dynamic tablenames如何处理动态表名
【发布时间】:2019-09-11 12:48:52
【问题描述】:

我有许多表需要使用 Linq 组合成一个结构

我需要处理许多具有相同结构但表名不同的表(财务数据跨越 20 年)。我可以创建代码来动态访问各种表格内容:

string tableName = "Trading.DataSources.Prices2017";
var results = DbContext.Set(Type.GetType(tableName));

但是,当我尝试使用 Cast 将结果从一个表转换为一个公共表(具有相同表结构的价格)时:

var newResults = results.AsQueryable().Cast<Price>().ToList();

我收到以下错误:

"System.NotSupportedException: '无法将类型 'Trading.DataSources.Prices2017' 转换为类型 'Trading.DataSources.Price'。LINQ to Entities 仅支持转换 EDM 基元或枚举类型。'"

我显然可以用我自己的转换方法进行这种转换。但是,这会导致同一代码块的多个版本以适应不同的表格,并且每年,当我有一组新的价格数据时,我必须修改我的代码以适应新年的表格名称。

有没有办法动态地(或一般地)处理这个问题?

【问题讨论】:

  • 您需要使用 创建一个通用接口,因为数据库表在实体模型中具有不同的类映射但具有相似的结构。请参阅以下内容:stackoverflow.com/questions/50136396/generic-entity-base-class
  • 非常感谢您的快速回复。我之前创建了一个通用版本,它避开了字符串表名 GetType 代码。然而,使用泛型并不能解决组合问题——现在,如何将泛型表结构(Prices2018、Prices 2017 等的类映射)转换为通用表结构(Prices 的类映射)而不编写特定的转换代码,即使用某些东西像 Linq 的 Cast 扩展?。
  • @jdweng - 我使用的是 EF 6,所以不确定如何在 EF 生成的代码中启用继承。
  • 您使用的是实体 DbContext,项目包含 c# 类和数据库表之间的映射数据。该链接显示了如何更改映射到数据库的 c# 类。

标签: c# linq dynamic casting tablename


【解决方案1】:

创建一个新的模型类SharedPrices。此类将包含这些表具有的所有相同值

var newResults = results.select(r => new SharedPrices{value1 = r.value1, value2 = r.value2}).ToList();

对于我的示例,所有价格表只有:

  • 值1
  • 值2

这些应该替换为您的实际类结构。

我为你做了更多的挖掘工作,我想感谢@Tyler-Long 他的回答here。 他的回答基本上指出,您可以使用 JSON(反)序列化来将一个类反映到另一个类中,而无需编写强制转换,只要它们具有 exact 相同的属性,如下所示:

using Newtonsoft.Json;

string tableName = "Trading.DataSources.Prices2017";
var tableType = Type.GetType(tableName);
var results = DbContext.Set(tableType);
Price newResults = JsonConvert.DeserializeObject<tableType>(JsonConvert.SerializeObject(results.ToList()));

我认为这将使您能够将表格转换为单一价格模型,而无需显式编写转换逻辑。唯一的缺点是它在 Newtonsoft.json 包上为您的项目添加了依赖项(可以通过 nuget 下拉)。不过这个包我个人用过,很靠谱。

【讨论】:

  • 感谢您的建议。这个解决方案或多或少是我迄今为止所做的。但是,我希望找到一个不那么冗长的解决方案,即类似于 Cast 扩展(它不适用于不同的映射)。再次感谢。
  • 这对我来说似乎是最不冗长的选项。根据我的经验,唯一的替代方法是使用继承(代码更多),或者在不存在隐式强制转换时编写显式强制转换(也有更多代码)。这总是可以抽象成一个方法,然后变成一个单行。
  • 如果您考虑必须设置 26 个值,那么它正在为某种更优雅的解决方案而尖叫 ;-)。不幸的是,Linq Cast 扩展在这种情况下确实有效。感谢您的反馈
  • LINQ Cast 扩展仅适用于 primitive types 和枚举。它不是用来映射类属性的。
  • 道歉我的意思是说(并重复)Cast 不起作用 - 这是我首先提出问题的原因(请参阅与我的原始提交相关的黄色文本)。我希望有另一种解决方法。我将接受您的回答,因为这或多或少是我在提交之前最初提出的。再次感谢,感谢其他人。
猜你喜欢
  • 2011-05-27
  • 2016-06-27
  • 1970-01-01
  • 2017-05-31
  • 2014-05-04
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多