代码之家  ›  专栏  ›  技术社区  ›  Ted

servicestack.ormlite:选择在运行时确定类型的poco(继承)

  •  1
  • Ted  · 技术社区  · 6 年前

    当我在设计时不知道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 { ... }
    

    我坚持演员和客户,但当我读回来,我基本上只有一个类型,可能是主键。.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);
    

    但是,这不会创建顶部列出的任何类;我需要将其键入基类,但它当然应该是正确的对象(因此,“customer”、“operator”等)。

    我怎样才能做到这一点?

    (我还注意到,mythz说过,在持久化数据时使用继承是一个坏主意,他提议“扁平化”层次结构。然而,我会不顾一切地说,在处理面向对象语言时,继承和多态性是不可避免的,99.9%的程序员都无法摆脱;-))

    1 回复  |  直到 6 年前
        1
  •  2
  •   mythz    6 年前

    在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%的程序员都无法摆脱;-))

    如果你要引用某人的话,请这样做 逐字 包括一个链接到你引用的来源,因为这是对我所说的歪曲。

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

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