web-dev-qa-db-ja.com

Azure DocumentDB DocumentクラスをPOCOクラスにキャストするにはどうすればよいですか?

Microsoft.Azure.Documents.Documentオブジェクトをクラスタイプにキャストする方法はありますか?

CosmosDBTriggerを使用してAzureFunctionクラスを作成しました。トリガーはMicrosoft.Azure.Documents.Documentの配列を受け取ります。レコード自体に関するメタデータにアクセスできるように、そのDocumentクラスを使用するのが好きですが、クラスタイプのデータを静的な方法で操作したいと思います。

ToStringを呼び出すと、データのJSON表現が表示されます。 Newtonsoftを使用してそのJSONをクラスタイプに手動で変換する必要がありますか?

8
Ryan

関数でDocumentをPOCOにマップする必要がある場合、それを行う最も簡単な方法は、提案した方法です。

document.Resource.ToString()メソッドを呼び出し、JSON.NETまたはお好みのjsonライブラリからDeserializeObjectを使用します。ただし、MicrosoftのCosmosDBライブラリでもJSON.NETを使用しているため、JSON.NETをお勧めします。

マッピング呼び出しは次のようになります。

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

5
Nick Chapsas

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間。

これは、強く型付けされたドキュメントモデルで作業する場合に、cosmosDBでデータアクセスを処理するためのIMHOの最もクリーンで推奨される方法です。

代替:動的

もう1つのトリックは、中間のキャストステップとしてダイナミックを使用することです。これはある意味で短くエレガントですが、個人的にダイナミックを使用すると常に少し汚く感じます。

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

別の方法:JObjectを読む

もう1つの方法は、ドキュメントをNewtonSoftのJObjectとして読み取ることです。これにはすべてのメタフィールドも含まれ、文字列表現間で余分なホッピングをすることなく、自分でさらにキャストすることができます。例:

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

代替案:同時にDocument + JObject

モデル内のドキュメントレベルのメタフィールドを本当に避けてアクセスしたい場合は、ちょっとしたリフレクショントリックを使用してJObjectインスタンスから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>();

リフレクショントリックは内部実装の詳細に依存しており、ライブラリ作成者による下位互換性の保証の対象ではないことに注意してください。

6
Imre Pühvel