次の方法で共有


OData

OData で簡単にストリーミング データを視覚化する

Louis Ross

コード サンプルのダウンロード

Open Data Protocol (OData) は RESTful プロトコルの 1 つです。SQL データベースを中心としたバッキング ストアのデータに対して、強力なクエリ操作や変更操作を実行できるように設計されています。リソース式とクエリの両方が HTTP 要求の URL を利用して作成され、結果が HTTP 応答として返されます。データ要求の整形、並べ替え、フィルター、およびページ切り替えを実行できるクエリの高度なサポートが、クエリ言語を通じて組み込まれています。OData は OASIS 標準の 1 つなので実装範囲が広く、Web ブラウザーをはじめとして、iOS、Android、Windows を基盤とする携帯電話やデバイスなど、すべての主要プラットフォームで使用できます。OData は、簡単に複数のプラットフォームで使用可能な標準ベースのサービスを提供するのに適した手段として評価されることがよくあります。基礎知識については、「その他のリソース」セクションのリンクを参照してください。

この記事では、OData のセマンティクスによって、ほぼリアルタイムの時系列ストリーミング データや SQL バッキング ストアのデータを公開するための媒体として OData が最適となっている理由を示します (この記事では、静的なバッキング ストアと区別するために "時系列" という言葉を使用します。この言葉を使用すると、文脈によって意味が異なる "リアルタイム" という言葉を使用しなくて済みます)。

この記事では、OData サービスを使用した産業オートメーション用時系列データ ストリーミング機能のサンプル実装を紹介します。図 1 は、Windows Presentation Foundation (WPF) を使用して C# で記述したサンプル テスト クライアントを示しています。このクライアントはサービスに接続していて、シンプルな LINQ クエリを使用して時系列データ ストリームを処理します。この処理については、後で詳しく説明します。既に述べたように、ブラウザーベース アプリケーションやデバイス アプリケーションなど、多数のクライアントが存在することが考えられます。

Windows Presentation Foundation (WPF) を使用して C# で記述したサンプル OData テスト クライアント
図 1 Windows Presentation Foundation (WPF) を使用して C# で記述したサンプル OData テスト クライアント

クライアントは OData サービスに接続して、複数の項目とサブスクリプションを管理します。各サブスクリプションに含める項目の組み合わせ、サブスクリプションの更新間隔、およびサブスクリプションの動的な監視については、どれもテスト クライアントで管理できます。項目とサブスクリプションの概念については、後で詳しく説明します。図 2 は、サブスクリプションの 1 つから時系列データをストリーミングしている、テスト クライアントの別のウィンドウを示しています。

OData サービスのサブスクリプションからストリーミングされている時系列データ
図 2 OData サービスのサブスクリプションからストリーミングされている時系列データ

この手法は、モノのインターネット (IoT) を基盤とするデバイスから取得したあらゆる時系列データに適用できます。IoT は発展を続けているため、降雨センサーから販売時点管理 (POS) 端末までのさまざまなデバイスにインターネット経由で直接アクセスできるようになってきています。この傾向が進むほど、すべてのデータにアクセスして管理するためのシンプルで一貫した方法が必要になります。この記事で説明する手法はインターネット経由の通信に最適です。このような通信により、IoT デバイスのデータをコンピューターなどのデバイスで使用でき、情報にアクセスして意味を与えることができるようになります。

この記事の例は、デモのみを目的としています。また、簡潔にするために機能も限定しています。つまり、公開するすべての項目は同じ整数型であり、データを提供する "デバイス" はシミュレーションです。しかも、ユーザーを認証したりユーザー ID やユーザーごとのセッションを提供したりするための試みは、行っていません。このような処理はどれも運用サービスには必要ですが、ここでは説明のために省略しています。

エンティティ モデルを設計する

OData サービスを定義するには、まず、エンティティ モデルを設計します。OData サービスは特定のベース URL (http://localhost:10001/TimeSeriesData.svc など) で公開され、このベース URL 配下の各 URL セグメントはエンティティ モデル内の各種リソースを表しています。ベース URL は OData サービスの展開方法に応じて変化する場合がありますが、ベース URL 配下の一連のリソース URL セグメントは、エンティティ モデルによって一定に決まります。

データベースに保存される通常の OData サービスでは、リソースをモデル化するために ADO.NET Entity Framework などの自動化ツールを使用できます。これに対して今回の時系列 OData サービスでは、リソースをメモリ内構造体として公開するので、手動でエンティティ モデルを生成します。時系列データ ストリーミング サービスのリソースとしては、以下に示す Items (項目)、Subscriptions (サブスクリプション)、および Samples (サンプル) が妥当でしょう。

すべての項目を取得する: http://localhost:10001/TimeSeriesData.svc/Items は、サービスがデータを提供するデバイスで使用可能な、すべてのデータを返します。各項目には、ID、名前、種類、状態、読み取り/書き込み機能、現在の値などのプロパティがあります。

すべてのサブスクリプションを取得する: http://localhost:10001/TimeSeriesData.svc/Subscriptions は、サービスに対する以前の呼び出しで作成されて保存されている、すべてのサブスクリプションを返します。サブスクリプションとは、項目をコレクションにグループ化するメカニズムです。サブスクリプションには、各サブスクリプションにグループ化されている項目を一定レートで一括サンプリングする追加機能もあります。各サブスクリプションには、ID、サブスクリプション間隔、各サブスクリプションに含まれる項目のコレクション、各サブスクリプションに含まれる項目に対するサンプルのコレクションなどのプロパティがあります。

すべてのサンプルを取得する: http://localhost:10001/TimeSeriesData.svc/Samples は、サービスでグローバルに公開している、すべてのサンプルを返します。今回の記事では、このクエリからは何も返しません。なぜなら、実際のシナリオでは無意味なクエリだからです。サンプルは必ずサブスクリプションと関連付けられているので、サンプルのルートでクエリを実行することはありません。ただし、WCF Data Services でサンプルをエンティティとして公開するには、ルート クエリが有効である必要があります。

以上の 3 つの基本エンティティに加えて、ここではエンティティ間の関連付けも作成します。Subscription リソースは、Sample と Item の両方に対して一対多で関連付けられています。

サブスクリプション内のすべてのサンプルを取得する: http://localhost:10001/TimeSeriesData.svc/Subscriptions(25)/Samples は、サブスクリプション 25 で取得できるすべてのサンプルを返します。このクエリは、既にクライアントで SubscriptionId = 25 となる Subscription エンティティを作成していることを前提にしています。各サンプルには、ID、サンプリングした項目の ID、サンプリング時点での項目の値/時刻/品質などのプロパティがあります。

サブスクリプション内のすべての項目を取得する: http://localhost:10001/TimeSeriesData.svc/Subscriptions(25)/Items は、サブスクリプション 25 に現在関連付けられている項目のコレクションを返します。このクエリは、既にクライアントで SubscriptionId = 25 となる Subscription エンティティを作成していて、この Subscription エンティティに項目を関連付けていることを前提にしています。

図 3 は、時系列 OData サービスのエンティティ モデルを示しています。Item はデバイスの物理エンティティであり、通常は文字列の名前や数値 ID で指定できます。一般的に Item には、デバイスで公開されている温度や圧力などの値と、最新サンプルのタイムスタンプや測定品質などのメタデータが含まれています。図 3 に示すように、Item は数値の ItemId に基づいて OData エンティティとして公開されます。

時系列 OData サービスで公開されるエンティティ モデル
図 3 時系列 OData サービスで公開されるエンティティ モデル

エンティティとしての Subscription は、デバイス項目の一部をグループ化してそのサブセットから一定時間ごとにサンプルを収集するために作成した、見かけ上のエンティティです。サブスクリプションは実際には存在していないので、Subscription エンティティがストアに格納されているように見える方法でエンティティを生成するためのメカニズムをサービスに用意する必要があります。

Sample エンティティは、Subscription エンティティよりもさらに一時的な性質が強いエンティティです。Sample エンティティは、特定の時点における単一の項目の値とメタデータを取得するために作成されます。通常、サブスクリプションは実行中に必要に応じて Sample エンティティを蓄積し、そのサブスクリプションに関連付けられている項目の最新サンプルを取得します。Sample エンティティが見せかけている点は、OData の要求を満たす大規模なエンティティ テーブルが存在していることです。実際には、Sample エンティティはクライアントに返された時点でストレージから削除されます。通常は同じサンプルをクライアントで複数回取得する必要がないので、このような処理は問題になりません。

サービス ランタイムがステートフルではなくなるような方法でこのようなメモリ内の抽象化を処理することは、OData サービスを拡張できるソリューションでは特に重要です。クライアントから順次呼び出しを実行する際は、前回の呼び出しでのサブスクリプションやサンプルに関する処理の詳細が記憶されるサービスに、依存してはなりません。

したがって、Subscription や Sample などの抽象エンティティが決して OData サービスで状態として記憶されることがないようにし、バッキング サービスまたはデバイスの一部と見なされるようにする必要があります。今回のサンプル OData サービスでは、シミュレーション層を実装することで実際のハードウェアとの依存関係を解消します。シミュレーションのハードウェアから各種エンティティを提供して、OData サービスで公開します。特に Item エンティティと Subscription エンティティについては、シミュレーション層で XML ファイルに保存します。

Sample エンティティは特別です。Sample は、シミュレートションのハードウェアに Sample エンティティが存在しないという意味で仮想のエンティティです。しかも、短命でもあります。一般的な時系列クライアントには、履歴を利用するクライアントとは異なり、最新の Sample だけが必要です。最新の Sample を読み取ったら、その Sample をサービスで破棄してかまいません。今回のサンプル コードでは、各 Sample エンティティに一意の ID を指定し、本当に OData クライアントが以前の Sample エンティティを任意のタイミングで要求する可能性を想定したままにします。ただし、シミュレーションのハードウェア層では以前の Sample が破棄されているので、実際にクライアントでこのような要求を実行しても失敗することになります。

WCF Data Services を使用してサンプル OData サービスを実装する

エンティティ モデルを定義したので、次は OData サービスを実装します。ASP.NET Web API フレームワークは強力な最新のテクノロジですが、今回は基本機能の実装をシンプルにするために、さかのぼって以前の WCF Data Services を採用します。

TimeSeriesDataService クラスは、DataService テンプレート クラスから派生することで、サービスを公開します。

public class TimeSeriesDataService : DataService<TimeSeriesEntities>
{
  public static void InitializeService(DataServiceConfiguration config)
  {
    // Initialize the service here...
  }
}

DataService 基底クラスのテンプレート パラメーターは、このサービスのエンティティ モデルを定義するクラスである TimeSeriesEntities を指定しています。先ほどの設計セクションで示したクエリを実行できるようにするために、TimeSeriesEntities クラスではクエリ可能なコレクションとして、Sample、Item、および Subscription の各エンティティを公開します (図 4 参照)。

図 4 コードでのエンティティ モデル

public partial class TimeSeriesEntities
{
  public IQueryable<Sample> Samples
  {
    get { return (new List<Sample>()).AsQueryable<Sample>(); }
  }
  public IQueryable<Item> Items
  {
    get
    {
      return (from item in ItemRegistry.Items
              select new Item(item.Id,
                              item.Name,
                              item.Value,
                              item.Time,
                              (int)item.Quality))
               .AsQueryable<Item>();
      }
  }
  public IQueryable<Subscription> Subscriptions
  {
    get
    {
      return (from subscription in SubscriptionRegistry.Subscriptions
              select new Subscription() { SubscriptionId =
              subscription.Id })
             .AsQueryable<Subscription>();
    }
  }
}

IQueryable<T> コレクションを返すパブリック プロパティを指定すると、WCF Data Services フレームワークで、HTTP URL として表現できる強力な OData クエリをすべて処理できるようになります。クエリ可能なコレクションをコードで提供すると、実際のフィルター、並べ替え、パターン マッチングなどが WCF Data Services フレームワークによって実行されます。

OData サービスを書き込み可能にする

サービスのエンティティを変更できるようにするには、もう少しコードを追加する必要があります。このコードは、変更コマンドに応じて WCF Data Services フレームワークによって呼び出されます。変更コマンドは、HTTP クライアントから POST、PUT、または DELETE 動詞を使用して送信されます。一般的な時系列データ サービスを使用すると、クライアントからさまざまな方法でサービスの状態を変更できるようになります。たとえば、項目の値の書き込み、サブスクリプションの作成と削除、サブスクリプションの項目の追加と削除などを実行できます。

WCF Data Services を使用する場合、この変更機能を実現するには、IUpdatable インターフェイスを実装します。クライアントから作成対象エンティティの説明と HTTP POST を送信すると、WCF Data Services フレームワークによって要求が処理され、必要に応じて IUpdatable インターフェイスの 12 のメソッドに要求が渡されます。

今回の最初の変更コードでは、サブスクリプションを作成および削除できるようにします。項目に値を書き込むなど、他の変更機能をサポートするには、IUpdatable インターフェイスの他のメソッドを実装する必要があります。

サブスクリプションの作成と削除を可能にするには、IUpdatable インターフェイスの CreateResource メソッドと DeleteResource メソッドを実装します (図 5 参照)。

図 5 サブスクリプションの作成と削除

public partial class TimeSeriesEntities : IUpdatable
{
  object IUpdatable.CreateResource(string containerName,
    string fullTypeName)
  {
    Type t = Type.GetType(fullTypeName, true);
    return Activator.CreateInstance(t);
  }
  void IUpdatable.DeleteResource(object targetResource)
  {
    MethodInfo deleteMethod =
      targetResource.GetType().GetMethod("Delete");
    if (deleteMethod != null && deleteMethod.IsPublic)
    {
      deleteMethod.Invoke(targetResource, null);
    }
  }
}

WCF Data Services フレームワークによって POST、PUT、および DELETE クライアント呼び出しの大半が管理されるので、記述するコードでは、内部実装に固有の型を処理する必要があるだけです。静的ファクトリ メソッドを実装することも、図 5 に示したようにリフレクションを使用して新しいインスタンスを作成することもできます。今回、リソース オブジェクトを削除するメカニズムの選択基準にしたのは、実装の細部です。つまり、すべてのリソース オブジェクトで、DeleteResource から呼び出し可能な Delete というメソッドを公開していることを考慮しました。必要に応じて、他の実装も選択できます。

LINQ で OData クライアントの処理を簡単にする

時系列 OData サービスの実装方法や公開方法にかかわらず、時系列 OData サービスの効果は、クライアント側でサービスを使用して実行できる処理によって決まります。これは、特に Microsoft .NET Framework の場合に当てはまります。なぜなら LINQ には、OData との直接のインターフェイスとなる一連の拡張機能があり、可能な限り多くのクエリがサービスに渡されるためです。LINQ を使用すると、複雑なクエリをクライアント コードで管理しやすくなります。たとえば、フィルターや並べ替えなどを比較的簡単に管理できます。

OData クライアントを Visual Studio で作成する

サンプル OData を実行しながら Visual Studio を起動し、"サービス参照の追加" ツールで OData サービスのベース URL を参照します。ツールによって OData メタデータが調査され、System.Data.Services.Client.DataServiceContext から派生したクラスが作成されて、TimeSeriesEntities という名前が設定されます。このクラスは OData サービス用にカスタマイズされていて、次のような型指定された DataServiceQuery<TElement> オブジェクトを返すプロパティが含まれています。これらの DataServiceQuery<TElement> オブジェクトは、WCF Data Services コードの各 IQueryable<TElement> コレクション用にカスタマイズされています。

public DataServiceQuery<Sample> Samples { get; }
public DataServiceQuery<Item> Items { get; }
public DataServiceQuery<Subscription> Subscriptions { get; }

これらの各 DataServiceQuery<TElement> インスタンスは IEnumerable を実装しているので、それぞれが LINQ クエリの対象になります。可能な限り、DataServiceQuery<TElement> オブジェクトに対して作成された LINQ クエリが OData クエリに変換されるので、フィルター、並べ替え、パターン マッチングの大半をサービスに対して実行できます。

以降の例では、サービスのベース URL として http://localhost:10001/TimeSeriesData.svc を dataAddress 変数に格納して使用します。また、以降のすべてのクエリ例では、dataContext という名前の TimeSeriesEntities オブジェクトが存在していて次のようにベース URL で初期化されていると想定しています。

TimeSeriesDataFeed.TimeSeriesEntities dataContext =
  new TimeSeriesDataFeed.TimeSeriesEntities(dataAddress);

最初に示す例では、http://localhost:10001/TimeSeriesData.svc/Items という OData URL を次の LINQ クエリから生成します。

var serviceQuery = from item in dataContext.Items
                   select item;

返された LINQ クエリを実行するには、次のコードを使用します。

serverItemsList = serviceQuery.ToList();

このコードを使用すると、URL が送信されて OData 応答が解析され、ルート サービス レベルでアクセスできるすべての Item エンティティ オブジェクトの列挙体が返されます。

このクエリは、デバイスの名前空間に含まれているすべての項目を参照する場合と同様の処理であることに留意してください。他のプロトコルでは、このような参照機能は追加の機能であり、機能を実装するには非常に骨が折れます。OData なら手間はかかりません。

もっと細かい処理を実行するクエリとしては、SubscriptionId = 25 となるサブスクリプションなど、特定のサブスクリプションに現在関連付けられているすべての項目を列挙するクエリが考えられます。次の LINQ クエリをご覧ください。

var subscriptionQuery =
  (from subscription in dataContext.Subscriptions.Expand("Items")
  where subscription.SubscriptionId == 25
  select subscription).FirstOrDefault();

このクエリは、次の OData URL を生成します。

http://localhost:10001/TimeSeriesData.svc/Subscriptions(25)/?$expand=Items

FirstOrDefault を呼び出すと、返される LINQ クエリが逆参照されて実行され、URL が送信されます。さらに、応答が受信されて解析されます。この例の結果は、1 つの Subscription エンティティ オブジェクトと、その Subscription エンティティ オブジェクトに関連付けられているすべての Item エンティティ オブジェクトです。サブスクリプションの項目を列挙するには、次のコードを使用します。

serverItemsList = serverSubscription.Items.ToList();

クライアント コードでは、次のような LINQ クエリを使用して、公開されているサンプルをサブスクリプションから取得します。

var subscriptionWithSamplesQuery =
  (from subscription in dataContext.Subscriptions.Expand("Samples")
  where subscription.SubscriptionId == 25
  select subscription).FirstOrDefault();

このクエリは、次の OData URL を生成します。

http://localhost:10001/TimeSeriesData.svc/Subscriptions(25)/?$expand=Samples

この例の場合、Subscription エンティティに関連付けられている Sample エンティティには、多数の Item エンティティに対するサンプル値が含まれています。おそらく、サブスクリプションに関連付けられている項目ごとに 1 つ以上のサンプルが存在しています。LINQ を使用している以上、サンプルを項目ごとにグループ化することにします。そのためには、前の LINQ クエリから返された IEnumerable コレクションに対して、次のようにローカル LINQ クエリを実行します。

var samplesInSubs = from sample in subscriptionWithSamplesQuery.Samples
                    group sample by sample.ItemIdSampled into sampleSubs
                    select sampleSubs;

この例は、時系列データの取得に関するごく基本的なユース ケースです。これは、OData トランザクションを生成する LINQ クエリからローカル データを操作するメモリ内の LINQ クエリへと自然に移行できることを示しています。この段階では、samplesInSubs は IEnumerable の IEnumerable、つまり ItemId ごとにサンプルがグループ化された、サンプル グループのコレクションです。このような形式のデータは、クライアントで自然に処理できます。

以上の OData クエリの例は、OData が秘めている表現力に比べればその足元にも及びません。はるかに強力なフィルター、並べ替え、およびサンプリングを実行できます。詳しい例については、「その他のリソース」のリンクを参照してください。

シンプルな WPF OData テスト クライアント

全体のまとめとして、OData サービスから取得した時系列処理データの概念を示すために、簡単な WPF アプリケーションを作成します。図 6 ~ 10 に示している OData Test Client では、先ほど説明した LINQ クエリとその他いくつかの LINQ クエリを使用して、サンプル OData サービスのデータの読み取りと書き込みを行います。

メイン画面を初めて表示するときには (図 6 参照)、複数の OData クエリを実行します。これらのクエリを実行することで、サービスに含まれているすべてのサブスクリプションと、サービスに含まれているすべての項目の名前と ID をリスト ボックスに表示できます。

OData Test Client のメイン ウィンドウ
図 6 OData Test Client のメイン ウィンドウ

図 7 からわかるように、左側のリスト ボックスでサブスクリプションを選択すると、そのサブスクリプションに含まれている項目の名前と ID が右側のリスト ボックスに表示されます。また、選択しているサブスクリプションの更新間隔を表示して設定することができ、選択しているサブスクリプションに関するいくつかのコマンド ボタンも有効になります。これらのボタンについては、後で説明します。

サブスクリプションを選択している状態
図 7 サブスクリプションを選択している状態

ストリップ チャート レコーダーなしでは時系列ストリーミング データの説明として不完全なので、CodePlex で見つけたすばらしい Dynamic Data Display プロジェクトを使用して、複数のペンで描画する動的表示を構築します (Dynamic Data Display for Silverlight ライブラリは Microsoft Research の製品であり、ライセンスの規定によって、ライブラリの用途が非営利目的に限られていることに注意してください)。単一のサブスクリプションに含まれているすべての項目のデータが、想定どおり右から左へ流れるように表示されます。サブスクリプションを選択して [Monitor] をクリックするたびに、図 8 に示すようなサブスクリプション モニター ダイアログ ボックスが表示されます。

単一サブスクリプションの監視
図 8 単一サブスクリプションの監視

多数の項目の時系列データを監視するだけでなく、同じ OData クエリを使用して、項目を参照することもできます (図 9 参照)。メイン ウィンドウ右側のリスト ボックスには、単一サブスクリプションまたはサービス全体に含まれているすべての項目が表示されますが、参照の場合は、サブスクリプションに含める項目を選択することもできます。参照ウィンドウを表示するには、メイン ウィンドウの左側でサブスクリプションを選択して、[Browse] をクリックします。項目を左 (サブスクリプションから削除する場合) または右 (サブスクリプションに追加する場合) に移動するとサブスクリプションが変更され、変更内容でサービスが更新されて、サービスを呼び出すたびに変更内容が保持されるので、保存ボタンは必要ありません。

サブスクリプションに含める項目の参照
図 9 サブスクリプションに含める項目の参照

最後に、同時に複数のサブスクリプションを監視できます (図 10 参照)。

同時に 4 つのサブスクリプションの監視
図 10 同時に 4 つのサブスクリプションの監視

時系列ストリーミング データに関する OData の課題と制限事項

私の勤務先は高密度かつ高スループットの時系列ストリーミング サービスとそのクライアントを専門としていますが、この用途における OData のパフォーマンスを定量化しようとしたことは (まだ) ありません。この記事の OData 手法を私の業界で一般的な他の手法と比べると、次のような短所が考えられます。

  • 現在のネットワーク環境では、どのようなデータ取得メカニズムについても、安全に使用するにはセキュリティ対策を講じる必要があります。たとえば、ユーザー認証は必須であり、必要に応じて暗号化も実施します。このような機能を提供するためのわかりやすい手段は、HTTP から HTTPS に移行することです。ただし、公開キー基盤 (PKI) を管理したり CPU リソースと帯域幅リソースの両方を読み込んだりすると負荷が増えるため、アプリケーションによってはこの手法が機能しない場合もあります。
  • この記事で説明した手法では、複数サブスクリプションの定義など、一定の状態をサービスで維持する必要があります。そのため、ユーザー認証と組み合わせる場合は、ユーザーごとにサービス側で一定の状態を維持する必要があります。スケーラビリティを確保するには、必要な状態情報がエンティティ モデルに組み込まれるようにし、サービス自体には組み込まれないように注意する必要があります。注意深くサービス自体をステートレスに保っている限り、クライアントの追加に比例してサービスが拡張するので、マルチテナント型クラウド ホスティングやサーバー ファームが実現します。
  • サービス要求を繰り返し高速で行うクライアントへの応答をキャッシュすると、パフォーマンスが向上する場合があります。この問題は、Subscriptions(x)/Samples エンティティ セットと、その他すべての 2 つに分類できます。特定のサブスクリプションに含まれているサンプルの要求は、ストリーミング データの取得方法そのものなので、多くの場合は群を抜いて頻繁に発生する要求です。サブスクリプションのサンプルは本質的には常にメモリ内に存在しているので、応答をキャッシュするとサービス設計に役立ちます。問題になるほど頻繁に他の種類の要求が発生する場合は、追加のキャッシュを検討する必要もあるでしょう。
  • OData の通信パフォーマンスによって、実質的な項目の密度やスループットが制限されるおそれがあります。私の勤務先ではこの制限事項を確認するために計測したことがまだないので、これは可能性にすぎません。SOAP ベースの転送と比較すると、OData の JSON ペイロードは SOAP エンベロープのオーバーヘッドよりも有利な場合があります。
  • OData やその他の REST ベースのサービスには、例外単位で報告するメカニズムも、重要なイベントの通知をクライアントにプッシュするメカニズムも用意されていません。すべてのデータ転送をクライアントから要求する必要があるので、採用できるのはプル モデルだけです。この制限事項は、業界で使用されていてインターネット経由の通信が可能なほとんどの他のプロトコルについても同様です。たとえば、OPC-UA は業界標準の SOAP ベース プロトコルですが、クライアント側で実行する公開/要求ループを使用して、通知を取得する必要があります。この手法の将来における発展に向けた有益な探求としては、SignalR などのサーバー側プッシュ テクノロジの使用を探ることが挙げられます。

この記事の例から考えると、OData が、次のようないくつものメリットを備えた現実的な手法であることは明らかでしょう。

  • クライアント コードの管理と配置が容易になる。
  • 携帯電話からデスクトップまでの複数のクライアント プラットフォームで、同じデータを使用できる。
  • OData は、数十~数百の項目密度と毎秒最大数百サンプルのスループットに対応した現実的な手法であるものの、高パフォーマンスへの対応については検証されていない。

次回の記事では、Reactive Extensions (Rx) を利用して OData サービスから "転送中のデータ" を使用する方法を探ります。

その他のリソース

OData の Web サイトodata.org (英語)。

OASIS OData 標準bit.ly/163s1gZ (英語)。

OData クエリ言語bit.ly/15PVBXv (英語) で正式な説明を参照してください。または、bit.ly/1zZYMqq (英語) で公開している LINQ を使用してクエリを生成する場合の制限事項など、マイクロソフトによる資料を参照してください。

OData、CKAN、および Microsoft Azure: OData を使用して大規模なデータ セットにアクセスする一般的な方法を示します (bit.ly/1LrzmYp、英語)。

OData クエリにマップされた LINQ クエリ: その他のサードパーティ製拡張機能を使用すると、LINQ を WCF Data Services クライアント ライブラリの外部まで拡張できます。基本的な WCF LINQ クエリと、このようなクエリを OData クエリにマップする方法の詳細については、msdn.microsoft.com/ja-jp/library/dd673933(v=vs.110).aspx を参照してください。

Dynamic Data Display: この本当に優れた動的データ表示用コントロールのセットは、bit.ly/1CI73B2 (英語) で入手できます。Dynamic Data Display をストリップ チャート レコーダーに使用することは、Dynamic Data Display のごく基本的な機能を利用しているにすぎません。


Louis Ross* は、Wonderware by Schneider Electric のマルチテクノロジ アーキテクトです。同社で彼はデバイス統合テクノロジの開発に 17 年間携わってきました。以前は、ハードウェアとファームウェアの設計を専門とする組み込みコントロールのフリーランス設計者として活動していました。*

この記事のレビューと貴重なフィードバックの提供に協力してくれた技術スタッフの Ming Fong (Schneider Electric) と Jason Young (マイクロソフト) に心より感謝いたします。
Ming Fong (Schneider Electric) は、Wonderware by Schneider Electric の開発マネージャーです。
Jason Young (マイクロソフト) は、マイクロソフトの Developer Experience & Evangelism に所属するシニア プログラム マネージャーであり、MS Dev Show (msdevshow.com、英語) の共同司会者でもあります。