inheritance - ServiceStack.OrmLite:选择在运行时确定类型的 POCO(继承)
问题描述
当我在设计时不知道 POCO 的确切类型时,如何使用 ServiceStack 中的 OrmLite 正确反序列化 POCO,但我只在运行时得到一个类型?
所以,像这样:
// Returns the object and can be cast to the correct subobject
public BaseClass ReadObject(Type typeOfObject, int id)
{
using (var db = _dbFactory.Open())
{
baseObject = db.Select<BaseClass>(typeOfObject, id); // need something here...
return baseObject;
}
}
...
BaseClass bc = ReadObject(someType, 3); // someType = Customer for example
...
class BaseClass { ... }
class Actor : BaseClass { ... }
class Customer : Actor { ... }
class Operator : Actor { ... }
我坚持 Actor 和 Customer,但是当我读回它们时,我基本上只有一个类型,可能还有主键。.Select<>
不起作用,因为我需要在运行时知道类型。
我发现了这个: 使用 servicestack ormlite 动态创建(并从中选择)表
如果我理解正确,在设计时获取类型未知的 POCO 的唯一方法是执行手动 SQL 语句,如答案中所示:
var modelDef = employeeType.GetModelMetadata();
var tableName = db.GetDialectProvider().GetQuotedTableName(modelDef);
var sql = $"SELECT * FROM {tableName}";
var results = db.Select<List<object>>(sql);
var results = db.Select<Dictionary<string,object>>(sql);
var results = db.Select<dynamic>(sql);
但是,这不会创建顶部列出的任何类;我需要将它类型转换为 BaseClass,但它当然应该是正确的对象(例如,'Customer'、'Operator' 等)。
我如何实现这一目标?
(我还注意到 Mythz 说过在持久化数据时使用继承是一个坏主意,并且他建议“扁平化”层次结构。但是,我会伸出脖子说在处理面向对象的语言时,继承和多态性是不可避免的,而且 99.9% 的程序员都无法摆脱它;-))
解决方案
在 OrmLite 中使用运行时类型的支持非常有限。
请参阅OrmLite 的无类型 API 支持,它允许您在处理运行时类型时访问一些插入、更新和删除 API 。
但是 SELECT 需要指定要选择的具体类型,即您可以选择基类:
var results = db.Select<BaseClass>(typeOfObject);
但结果只会填充BaseClass
属性。
一种可能的解决方案是使用动态字典结果集 API将结果选择到对象字典列表中,例如:
List<Dictionary<string,object>> results = db.Select<Dictionary<string,object>>(q);
然后使用FromObjectDictionary Reflection Utils将其转换为后期绑定类型,例如:
List<BaseClass> customers = results.Map(x => (BaseClass)x.FromObjectDictionary(customerType));
引用来源
(我还注意到 Mythz 说过在持久化数据时使用继承是一个坏主意,并且他建议“扁平化”层次结构。但是,我会伸出脖子说在处理面向对象的语言时,继承和多态性是不可避免的,而且 99.9% 的程序员都无法摆脱它;-))
如果您要引用某人,请逐字逐句,包括指向您引用的来源的链接,因为这是对我所说的内容的歪曲。
您可能会参考我的回答,强烈建议不要使用继承和基本类型属性以及未知的后期绑定类型,例如 DTO 中的接口和对象。这是为了避免与特定的序列化实现耦合,并且是运行时序列化问题的主要来源,这与创建定义良好的可互操作服务的目标背道而驰。您可以避免使用此指南,但您的服务仅适用于特定的序列化程序实现,在不同的语言中失败并且元数据支持有限,因为它们无法静态推断您的服务合同中使用未知类型的漏洞。
但是这句话与 OrmLite 中的继承没有任何关系,您的 POCO 可以愉快地拥有任何级别的继承。问题是您正在尝试查询未知的后期绑定类型,其中 OrmLite 是具有类型化 API 的代码优先 ORM,需要访问具体类型以支持其类型化表达式 API 并填充其类型化结果。我上面的回答包括 OrmLite 对无类型访问的有限支持。
推荐阅读
- excel - VBA 代码:Excel 范围未正确粘贴到 Outlook
- junit - 使用 JUnitCore 运行时,TestWatcher 不会捕获失败的测试
- c - 找不到如何正确使用 ptrace()
- python - 无法在 Windows 上使用键盘 Ctrl+C 中断线程化 Python 控制台应用程序
- java - 通过 selenium 禁用 chrome 中的文本自动填充
- enums - 解构枚举时是否可以向上转换为特征?
- python - 如何使用 POST GET 传递 access_token
- r - 使用 dplyr 有条件地将一列中的值替换为另一列中的值
- json - 尝试使用文件加载器和 webpack 加载大型 json 文件
- css - 如何在 Bootstrap 4 中居中对齐文本