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

如何将Azure DocumentDB文档类强制转换为我的Poco类?

  •  5
  • Ryan  · 技术社区  · 7 年前

    有没有办法 Microsoft.Azure.Documents.Document 反对我的类类型?

    我已经编写了一个Azure函数类, CosmosDBTrigger . 触发器接收一个数组 Microsoft.azure.documents.document文档 . 我喜欢吃那个 Document 类,以便我可以访问有关记录本身的元数据,但我也希望以静态方式与来自类类型的数据交互。

    我在调用时看到数据的JSON表示 ToString . 我应该使用newtonsoft手动将JSON转换为类类型吗?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Nick Chapsas    7 年前

    如果你需要绘制 Document 对于函数中的poco,那么最简单的方法就是您建议的。

    呼叫 document.Resource.ToString() 方法和使用 DeserializeObject 从json.net或您喜欢的json库。不过,建议使用json.net,因为微软的cosmossdb库也会使用它。

    您的映射调用将如下所示:

    var yourPoco = JsonConvert.DeserializeObject<YourPocoType>(document.Resource.ToString())

        2
  •  4
  •   Imre Pühvel    7 年前

    虽然Nick Chapsas提供的解决方案有效,但我想提供一些更好的选择。

    首选解决方案-改进您的模型

    首先,如果您对额外的元字段感兴趣,那么您可以 将所选属性包含到数据访问模型中 他们会被填上的。例如:

    public class Model
    {
        public String id { get; set; }
        public String _etag { get; set; }
        //etc.
    }
    

    然后,您可以使用现有的API来反序列化所有人都很清楚和熟悉的内容。例如:

    var explicitResult = await client.ReadDocumentAsync<Model>(documentUri);
    Model explicitModel = explicitResult.Document;
    

    如果您希望下一个层模型(例如:域模型)没有那些特定于存储的元字段,那么您需要转换到另一个模型,但这不再是COSMOSDB级别的问题,并且有大量通用映射器可以在POCO之间转换。

    如果您使用强类型文档模型,这是imho在cosmossdb中处理数据访问最干净和推荐的方法。

    备选方案:动态

    另一个技巧是使用动态作为中间铸造步骤。这在某种程度上是短小而优雅的,但个人使用dynamic总是感觉有点脏:

    var documentResult = await client.ReadDocumentAsync(documentUri);
    Model dynamicModel = (dynamic)documentResult.Resource;
    

    备选方案:阅读 JObject

    另一种选择是将文档作为newtonsoft的 工作项目 . 这还将包括所有的元字段,您可以自己对其进行进一步的强制转换,而无需在字符串表示之间进行所有额外的跳转。例子:

    var jObjectResult = await client.ReadDocumentAsync<JObject>(documentUri);
    Model JObjectResult = jObjectResult.Document.ToObject<Model>();
    

    备选方案: Document + 工作项目 同时

    如果您真的想要避免模型中的文档级元字段并仍然访问它们,那么您可以使用一些反射技巧来获取 工作项目 来自 文件 实例:

    var documentResult = await client.ReadDocumentAsync(documentUri);
    Document documentModel = documentResult.Resource;
    
    var propertyBagMember = documentResult.Resource.GetType()
        .GetField("propertyBag", BindingFlags.NonPublic| BindingFlags.Instance);
    Model reflectionModel = ((JObject)propertyBagMember.GetValue(documentResult.Resource))
        .ToObject<Model>();
    

    注意反射技巧依赖于内部实现细节,并且不受库作者向后兼容性保证的约束。