ServiceStack.OrmLite:选择类型在运行时确定的POCO(继承)

ServiceStack.OrmLite: Selecting POCOs where Type is determined in runtime (inheritance)

当我在设计时不知道 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,但是当我读回它们时,我基本上只有一个Type,可能还有主键。 .Select<> 不起作用,因为我需要在运行时知道类型。

我发现了这个:

如果我理解正确,在设计时获取类型未知的 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 说过在持久化数据时使用继承是一个坏主意,他建议 "flatten" 层次结构。但是,我会伸出我的脖子并说在处理面向对象语言时,继承和多态性是不可避免的,而且 99.9% 的编码人员都无法避免 ;-))

OrmLite 中对使用运行时类型的支持非常有限。

在处理运行时类型时请参阅 OrmLite's Untyped API Support which gives you access to some Insert, Update and Delete APIs

但是 SELECT 需要指定 select 的具体类型,即你可以 select 进入基础 class 与:

var results = db.Select<BaseClass>(typeOfObject);

但结果只会填充 BaseClass 属性。

一个可能的解决方案是使用 Dynamic Dictionary ResultSets API 到 select 结果到对象字典列表中,例如:

 List<Dictionary<string,object>> results = db.Select<Dictionary<string,object>>(q);

然后使用FromObjectDictionary Reflection Utils将其转换为后期绑定类型,例如:

List<BaseClass> customers = results.Map(x => (BaseClass)x.FromObjectDictionary(customerType));

引用来源

(I have also noted that Mythz has said that using inheritance when persisting data is a bad idea and that he proposes to "flatten" the hierachy. However, I would stick my neck out and say that when dealing with Object Oriented languages, inheritance and polymorphism is unavoidable and not something 99.9% of the coders out there can do away with ;-))

如果你要引用某人的话,请逐字在你引用的来源中加上link,因为这是对我的错误陈述说过。

您可能引用了我强烈推荐 against using inheritance and base type properties and unknown late-bound types like interfaces and objects in DTOs 的回答。这是为了避免耦合到特定的序列化实现,并且是运行时序列化问题的主要来源,这与创建定义明确的可互操作服务的目标背道而驰。您可以避免此指南,但您的服务将仅适用于特定的序列化程序实现,在不同的语言中失败并且元数据支持有限,因为它们将无法静态推断您的服务合同中使用未知类型的漏洞。

但是这句话与 OrmLite 中的继承没有任何关系,您的 POCO 可以愉快地拥有任何级别的继承。问题是您正在尝试查询一个未知的后期绑定类型,因为 OrmLite 是一个代码优先的 ORM,带有类型 API 需要访问具体类型以支持其类型表达式 API 并填充其键入的结果。我上面的回答包括 OrmLite 对非类型化访问的有限支持。