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

时间:2018-07-16 10:10:19

标签: inheritance servicestack ormlite-servicestack

当我在设计时不知道POCO的确切类型,而我在运行时只得到Type时,如何使用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 <>不起作用,因为我需要在运行时知道类型。

我发现这样: Create (and select from) a table dynamically using 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%的编码人员可以消除;-))

1 个答案:

答案 0 :(得分:2)

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

请参见OrmLite's Untyped API Support,它使您可以在处理运行时类型时访问某些Insert, Update and Delete APIs

但是SELECT需要指定要选择的具体类型,即,您可以使用以下方法选择基类:

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

但是结果只会填充BaseClass属性。

一种可能的解决方案是使用Dynamic Dictionary ResultSets 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%的编码人员可以消除;-))

如果您要引用某人,请 verbatim ,包括指向您所引用来源的链接,因为这是对我所说内容的虚假陈述。

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

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