如何将Azure DocumentDB Document类转换为POCO类?

Rya*_*yan 7 c# azure azure-cosmosdb

有没有一种方法可以将Microsoft.Azure.Documents.Document对象转换为我的类类型?

我用编写了一个Azure函数类CosmosDBTrigger。触发器接收的数组Microsoft.Azure.Documents.Document。我喜欢使用Document该类,以便可以访问有关记录本身的元数据,但是我也想以静态方式与我的类类型中的数据进行交互。

调用时,我看到了数据的JSON表示形式ToString。是否应该使用Newtonsoft将JSON手动转换为我的类类型?

Nic*_*sas 9

如果您需要Document在函数中将您的 POCO映射到您的 POCO,那么最简单的方法就是您所建议的。

从 JSON.NET 或您喜欢的 json 库调用该document.Resource.ToString()方法并使用DeserializeObject。建议使用 JSON.NET,因为 Microsoft 的 CosmosDB 库也使用它。

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

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


Imr*_*vel 6

虽然尼克·查普萨斯(Nick Chapsas)提供的解决方案有效,但我想提供一些更好的选择。

首选解决方案-改善模型

首先,如果您对额外的元字段感兴趣,那么您始终可以将所选属性包括在数据访问模型中,并将其填充。例如:

public class Model
{
    public String id { get; set; }
    public String _etag { get; set; }
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用现有的API来反序列化所有人都熟悉且明确的多数民众赞成。例如:

var explicitResult = await client.ReadDocumentAsync<Model>(documentUri);
Model explicitModel = explicitResult.Document;
Run Code Online (Sandbox Code Playgroud)

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

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

替代方案:动态

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

var documentResult = await client.ReadDocumentAsync(documentUri);
Model dynamicModel = (dynamic)documentResult.Resource;
Run Code Online (Sandbox Code Playgroud)

备选:阅读 JObject

另一种选择是将文档阅读为NewtonSoft的JObject。这还将包括所有meta字段,您可以自己进行进一步转换,而无需在字符串表示之间进行所有额外的跳跃。例:

var jObjectResult = await client.ReadDocumentAsync<JObject>(documentUri);
Model JObjectResult = jObjectResult.Document.ToObject<Model>();
Run Code Online (Sandbox Code Playgroud)

备选:Document+ JObject同时

如果您确实希望避免模型中的文档级元字段并仍然访问它们,则可以使用一些反射技巧来JObjectDocument实例中获取:

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>();
Run Code Online (Sandbox Code Playgroud)

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