本文章是由機器翻譯。

OData

視覺化流資料與 OData 最簡單的方法

Louis Ross

下載代碼示例

開放資料協定 (OData) 是 rest 風格的協定,旨在使功能強大的查詢以及對後備存儲,通常是 SQL 資料庫中的資料修改操作。在 HTTP 回應中返回的結果與通過 HTTP 要求的 URL 形成資源運算式和查詢。複雜的查詢,它可以塑造、 順序、 篩選器和頁面的資料請求的支援是建立在通過一種查詢語言。OData 是 OASIS 標準,因為它得到廣泛實施,並可以跨所有流行的用戶端平臺,如 Web 瀏覽器,以及電話和基於 Android 和 Windows 的 iOS 設備消耗。OData 經常被看作是好的方式,提供可以容易地消耗跨多個平臺的基於標準的服務。一些首次置業的連結,請參閱"其他參考"。

在本文中,我將演示為什麼語義的 OData 使它完美車輛因揭露近即時時間序列流資料,以及資料從 SQL 備份存放區。(我使用時間數列來區分從靜態的後備存儲區中。這避免了使用即時,在不同上下文中具有不同的含義)。

這篇文章將演示示例執行使用 OData 服務工業自動化時間序列資料流程能力。圖 1 演示示例測試用戶端,寫在 C# 中使用Windows Presentation Foundation(WPF),連接到服務並使用簡單的LINQ查詢來處理時間序列資料的流。我不久就會討論這在更多的細節。如前所述,許多可能的用戶端存在,包括基於瀏覽器和設備應用程式。

樣品 OData 測試用戶端寫在 C# 中使用Windows Presentation FoundationFoundation
圖 1 樣品 OData 測試用戶端寫在 C# 中使用Windows Presentation Foundation

用戶端連接的 OData 服務來管理多個專案和訂閱。每個訂閱中的專案的成員,該訂閱更新的時間間隔和動態監測中的訂閱所有通過可以管理測試用戶端。我將涵蓋專案和訂閱的更多細節稍後的概念。圖 2 正在流從一個訂閱的時間序列資料顯示的測試用戶端,另一個視窗。

時間序列資料流程從 OData Service 中的訂閱
圖 2 時間序列資料流程從 OData Service 中的訂閱

這種技術可以擴展到任何時間序列資料從設備上物聯網 (物聯網)。隨著物聯網的不斷打造出了,從雨感應器到銷售點終端設備越來越可用直接在互聯網上。進一步這個過程去,越需要簡單、 一致的方式來訪問和管理的所有資料。這項技術我展示在這裡非常適合於在 internet 上,允許資料從物聯網設備能夠被電腦和其他設備,使資訊可訪問的、 有意義。

我舉的例子是用於演示目的,和範圍能力為明確起見:它公開的專案都是相同的整數類型 ; 提供資料的"設備"是一種類比 ; 並沒有試圖來驗證使用者的身份或提供使用者身份和每個使用者會話。所有這些事情將是必要的一家生產服務,但出於演示的目的已被淘汰。

設計實體模型

定義 OData 服務的第一步設計的實體模型。OData 服務暴露在特定的基 URL 例如 HTTP://localhost:10001/TimeSeriesData.svc,和下面這基 URL 的每個 URL 分段表示一種不同的實體模型內的資源。基 URL 可能會更改,具體取決於如何部署了 OData 服務,但實體模型將決定一組固定的資源 URL 分段在它之下。

由資料庫支援的典型 OData 服務,可以使用自動化的工具 (如ADO.NETEntity Framework建模資源。我的時間序列 OData 服務,另一方面,公開資源作為記憶體中的結構,所以我用手來生成實體模型。一套合理的流媒體服務的時間序列資料的資源可能是專案、 訂閱和範例:

獲取所有專案:HTTP://localhost:10001/TimeSeriesData.svc/Items 應返回可用設備,該服務提供的資料中的所有項。每個專案應該有屬性 (如 id、 名稱、 類型、 狀態、 讀寫能力,當前值等。

獲取所有的訂閱:HTTP://localhost:10001/TimeSeriesData.svc/Subscriptions 應返回已創建並堅持以以前調用該服務的所有訂閱。訂閱是一種機制來對專案進行分組到集合。訂閱附加功能是分組到每個訂閱的專案在一起是以特定速率抽取的樣本。每個訂閱應具有屬性,如 id、 訂閱間隔、 其收藏的物品,其收藏的那些專案的樣品。

獲取所有範例:HTTP://localhost:10001/TimeSeriesData.svc/範例應返回由服務全球公開的所有樣品。對於本文來說,此查詢永遠不會返回任何東西,因為在現實生活中的場景,這是毫無意義的查詢。範例都與一個訂閱,所以應該沒有質疑的根本原因相關聯。然而,要暴露樣本作為實體的 WCF 資料服務,根查詢必須有效。

除了這三個基本的實體,我添加了它們之間的關聯。訂閱資源是與範例和專案從一到多關聯。

獲取所有範例內的訂閱:HTTP://localhost:10001/TimeSeriesData.svc/Subscriptions(25) /範例應返回可用於訂閱 25 的所有樣品。 這假定用戶端以前創建了訂閱實體與 SubscriptionId = 25。 每個樣本應具有屬性 (如身份證件 ; 進行採樣 ; 項的 id 和值、 時間和它進行採樣時在該專案的品質。

獲取訂閱中的所有項:HTTP://localhost:10001/TimeSeriesData.svc/訂閱 25/專案應返回的當前訂閱 25 與相關聯的項的集合。 這假定用戶端以前創建訂閱的實體,與 SubscriptionId = 25 和與它相關聯的專案。

圖 3 顯示時間序列 OData 服務的實體模型。專案是在設備中,通常通過一個字串的名稱或數位 id 可定址的物理實體。 專案通常包含由該設備,如溫度或壓力,以及中繼資料 (如時間戳記的最新的樣品和品質的測量值。作為圖 3 所示,他們由其數值 ItemId 公開作為 OData 實體。

由時間序列 OData 服務公開的實體模型
圖 3 由時間序列 OData 服務公開的實體模型

作為一個實體,訂閱是發明一起設備專案的子集,並在一段固定的時間,從該子集收集樣本的小說。因為訂閱並不真的存在,在要生成的實體,在這種情況下他們似乎支援的一家商店的服務必須有某種機制。

抽樣實體都比訂閱更短暫。示例實體被發明來捕獲特定時刻的值和中繼資料的單個專案。當訂閱運行時,它通常積累抽樣實體需要捕獲與該訂閱關聯項的近期的樣本。與樣品實體小說是遼闊的實體存在履行 OData 請求。在現實中,抽樣實體被刪除從存儲一樣快,它們返回到用戶端。因為用戶端通常不感興趣不止一次獲得相同的樣本,但這不是一個問題。

這些記憶體中抽象狀態刪除服務運行時的方式處理關鍵在於允許 OData 服務規模的解決方案 — — 從用戶端的順序調用不應該依賴于服務記住有關訂閱或在以前的調用中的樣品處理的詳細資訊。

這意味著抽象的實體,例如訂閱和範例必須永遠不會記住作為 OData 服務的狀態。相反,他們必須考慮支援服務或設備的一部分。在我的示例 OData 服務,我實現了一個類比層,以消除任何對真正的硬體的依賴性。實體提供了類比的硬體,並簡單地通過 OData 服務公開。尤其是,專案和訂閱的實體將保留由類比層到 XML 檔。

示例實體是一種特殊情況。範例都是虛擬的在意義上沒有樣品實體存在於類比的硬體,但範例也是短暫的。典型的時間序列客戶 — — 而不是歷史的客戶 — — 感興趣只是在最近期的範例。一旦讀取這些範例時,他們可以丟棄在服務中。在我的示例代碼中,我提供一個唯一的 Id,每個示例實體和保持 OData 用戶端可能會隨時問為真的老了範例的小說。然而,舊範例被遺忘類比的硬體層,所以實際上這樣做的任何用戶端將會失望了。

執行使用 WCF 資料服務的示例 OData 服務

既然定義了實體模型下, 一步是實現 OData 服務。ASP.NETWeb API 框架是一個強大的現代選擇,但在年長的 WCF 資料服務,為其簡單的實現的基礎上下降回來的了。

TimeSeriesDataService 類公開服務範本類 DataService 中派生:

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

DataService 基類的範本參數指定的類的定義這項服務,時序的實體模型­實體。若要允許在前面的設計一節所示的查詢,TimeSeriesEntities 類樣品、 專案和訂閱的實體作為公開可查詢的集合,如中所示圖 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 資料服務框架來處理所有強大 OData 查詢可以表示為 HTTP Url。可查詢的集合,提供您的代碼和框架執行實際的篩選、 排序、 模式匹配,等等。

使 OData 服務可寫

要允許實體在該服務中被修改,你必須添加一個小的更多代碼。通過修改命令後,付諸表決或刪除動詞使用 HTTP 用戶端發送的回應的 WCF 資料服務框架將會調用此代碼。一個典型的時間序列資料服務允許用戶端修改以各種方式服務的狀態:寫入值的物品 ; 創建和刪除訂閱 ; 添加和刪除專案的訂閱 ; 和更多。

使用 WCF 資料服務時,可實現 IUpdatable 介面提供此修改方面的能力。當用戶端發送 HTTP POST 一份詳細的實體創建時,資料服務框架處理該請求,將請求傳遞到 12 的 IUpdatable 介面方法,根據需要。

我第一次的服務修改代碼中可創建和刪除訂閱。你需要來實現其他 IUpdatable 介面方法,以支援其他修改功能,如一個值寫入一項。

我訂閱的創建和刪除通過啟用執行的 CreateResource 和 DeleteResource IUpdatable 的方法,如中所示圖 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 資料服務框架負責管理的職位,付諸表決,並刪除用戶端調用,大部分,只是需要我的代碼來處理任何特定于我的內部實現的類型。您可以選擇執行靜態工廠方法或使用反射來創建新的實例,如中所示圖 5。我選擇機制要刪除資源物件依賴于實現的細節 — — 我的資源的物件都公開要求刪除,可以從 DeleteResource 調用一個方法。您可以選擇所需的其他實現。

OData 用戶端變得更便捷,使用LINQ

不管如何時間序列 OData 服務的實現和暴露,其威力在於消費的用戶端可以用它做什麼。這是與 Microsoft.NET Framework 中,尤其如此,因為LINQ具有一組直接向 OData 服務,向盡可能服務傳遞盡可能多的查詢介面的擴展。使用LINQ便於用戶端代碼來管理複雜的查詢,包括篩選、 排序和其他相對輕鬆。

在Visual Studio中創建 OData 用戶端

與我的樣品 OData 服務運行,我開始Visual Studio,並指出添加服務引用工具 OData 服務的基 URL。該工具檢查 OData 中繼資料和創建 System.Data.Services.Client.DataServiceCoNtext,從派生的類並稱之為 TimeSeriesEntities。此類為 OData 服務,自訂,包括屬性的返回類型的 DataServiceQuery < TElement > 為每個 IQueryable < TElement > 自訂的物件 在 WCF 資料服務的代碼的集合:

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

每個這些 DataServiceQuery < TElement > 實例實現 IEnumerable,所以每個人都是LINQ查詢的目標。在可能的情況下,LINQ查詢形成針對 DataServiceQuery < TElement > 物件將轉化 OData 查詢,允許很多的篩選、 排序和模式匹配發生在服務。

下面的示例中,將使用服務基地網址 HTTP://localhost:10001/TimeSeriesData.svc,包含在變數 dataAddress。為所有查詢下面的示例中,名為 dataCoNtext 的 TimeSeriesEntities 物件被假定存在,並已初始化使用服務的基 URL:

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

作為一個初學者的例子,OData URL HTTP://localhost:10001/TimeSeriesData.svc/Items 是通過以下的LINQ查詢生成的:

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

返回的LINQ查詢可以與執行:

serverItemsList = serviceQuery.ToList();

發送 URL 和接收以及導致枚舉所有專案實體物件的可用服務根級別的 OData 回應進行解析。

請注意此查詢類似于流覽設備命名空間中的所有專案。在其他協定中,流覽像這是添加的功能,和很多精力來定義和執行功能的能力。隨著 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 發送及接收的回應進行解析。這一次,結果是具有與此訂閱關聯的所有專案實體物件的單個訂閱實體物件。訂閱專案可以與枚舉:

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

在這種情況下,樣品與訂閱實體關聯的實體包含許多專案實體,可能與訂閱關聯的每個專案的一個或多個樣品的採樣的值。只要我使用LINQ,我會與當地LINQ查詢操作以前的LINQ查詢所返回的 IEnumerable 集合按專案分組樣本:

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 測試用戶端

把一切都放在一起,我寫了小的 WPF 應用程式來展示時間序列的概念處理來自 OData 服務的資料。所示的 OData 測試用戶端數位 6-10 使用LINQ查詢我探索了早些時候,再加上幾個其他人,要從中讀取資料並將資料寫入樣品 OData 服務。

主畫面是當第一次啟動時 (見圖 6),它使多個 OData 查詢,允許它填寫清單方塊中的服務,以及名稱和 Id 的服務中的所有專案的所有訂閱。

OData 測試用戶端的主視窗
圖 6 OData 測試用戶端的主視窗

圖 7,你看到選擇左側的清單方塊中的訂閱讀取的專案的名稱和 Id 到右側的清單方塊,允許您讀取和設置該訂閱的更新間隔,該訂閱中的專案,使該訂閱,當我走,我將描述幾個命令按鈕。

訂閱處於選中狀態
圖 7 訂閱處於選中狀態

於是在 CodePlex,發現優秀的動態資料顯示專案用於生成多筆動態顯示,沒有討論時間序列資料流程是橫條圖表記錄器,不完整的。(請注意 Silverlight 庫動態的資料顯示是微軟研究院的產品,其許可證規定圖書館對於非商業使用只)。單個訂閱中的所有項的資料卷按預期從右至左。你得到一個訂閱監視器對話方塊類似于圖 8 每次你選擇訂閱並按顯示器。

監測單個訂閱
圖 8 監測單個訂閱

除了監控時間序列資料從多個專案,相同的 OData 查詢可用於執行專案的流覽,如中所示圖 9。從單個訂閱或作為一個整體服務的所有專案都顯示在右側的清單方塊中,但流覽也意味著選擇哪些項要包含在訂閱中。要得到一個流覽視窗,請選擇左邊的訂閱並按瀏覽按鈕。更改向訂閱由移動專案 (離開訂閱) 或向右 (進訂閱) 在該服務中進行更新,並保持每次服務調用由,所以沒有 Save 按鈕需要。

流覽專案列入訂閱
圖 9 流覽專案列入訂閱

最後,可以一次,監視多個預訂,如中所示圖 10

一次監測四個訂閱
圖 10 一次監測四個訂閱

挑戰和限制 OData 時間序列流資料

雖然我公司專業從事高密度、 高輸送量的時間序列流媒體服務和用戶端,沒有嘗試取得了 (尚) 來量化這種使用 OData 的性能。當我比較我 OData 的方式,打擊我的行業中常見的其他方法,我看到潛在的一些缺點:

  • 在當今的網路環境沒有安全保障,包括強制使用者身份驗證和可選的加密,可以安全地使用沒有資料獲取機制。顯而易見的方法來提供這些功能是從 HTTP 轉移到 HTTPS。公開金鑰基礎結構 (PKI) 管理的額外負擔和 CPU 和頻寬資源的載入,可能使這種方法不可行的對於某些應用程式。
  • 在這篇文章中詳細闡述的做法需要服務堅持某種狀態的多個訂閱定義等。當結合使用者身份驗證,這意味著一些國家必須堅持在服務端為每個使用者。出於可伸縮性方面的考慮,必須小心以確保任何所需的狀態資訊將納入實體模型,而不能實施作為服務本身的一部分。只要仔細保存服務本身無國籍問題,服務應該是線性的多租戶雲託管與添加的客戶和伺服器農場應該有可能。
  • 為進行快速的重複的服務請求的用戶端緩存的回應可以是一個性能增強。這個問題有兩種口味:Subscriptions(x) /範例實體集和其他一切。範例從特定的訂閱是可能要到目前為止,最常見的請求,因為這就是如何獲得了流資料。這適用于服務的設計,因為訂閱樣品是由定義總是記憶。如果其他類型的請求發生與足夠的頻率是一個問題,可能需要考慮附加緩存。
  • OData 鋼絲性能可能會限制其有效的物料密度或輸送量。在我公司,我們還沒打的度量來確定這一點,並就只有一種可能性。與基於 SOAP 傳輸相比,JSON 有效載荷從 OData 可媲美到 SOAP 信封的開銷。
  • OData 和其他基於 REST 的服務向用戶端提供沒有機制報告的異常,或推式通知的重要事件。轉讓必須由用戶端請求的所有資料,因此,只有拉模型都是可能的。這種限制是大多數其他協定用於工業能夠穿越 Internet 相媲美。例如,OPC UA 是業界標準的基於 SOAP 協定,,需要被泵使用發佈請求迴圈驅動的用戶端的通知。這項技術未來發展的可貴探索將探索那麼 SignalR 伺服器端推送技術的使用。

從這篇文章中的例子,似乎明確 OData 是一個可行的方法有以下幾個好處:

  • 用戶端代碼更加易於管理和部署。
  • 多個用戶端平臺 — — 從手機到桌面 — — 可以使用相同的資料。
  • OData 是一個可行的方法,為幾十年到幾個幾百個專案和輸送量達每秒幾個幾百個樣品的密度,但未經過高性能。

在我的下一篇文章,我會跟進與探索如何從 OData 服務與無功擴展 (Rx) 消費"在飛行中的資料"。

其他參考

OData 網站: odata.org

綠洲 OData 標準: bit.ly/163s1gZ

OData 查詢語言: ,請參閱在規範說明 bit.ly/15PVBXv 或微軟採取包括限制使用LINQ來生成查詢,在 bit.ly/1zZYMqq

OData、 CKAN 和微軟 Azure: 如何 OData 通常提供對大型資料集的訪問 (bit.ly/1LrzmYp)。

LINQ查詢映射到 OData 查詢: 有擴展LINQWCF 資料服務用戶端庫之外的其他協力廠商擴展。在詳細的基本的 WCFLINQ查詢,和它們如何映射到 OData 查詢 bit.ly/1zf8Gp7

動態資料顯示: 我發現這真的優秀組控制項用於動態資料顯示在 bit.ly/1CI73B2。幾乎沒有為橫條圖表記錄儀使用劃痕表面的它的能力。


Louis Ross* 是一個多功能的技術建築師為傑出的施耐德電氣,在那裡他一直在開發設備集成技術為 17 年。 此前,他作為一名設計師,嵌入的控制項,專業從事硬體和固件的設計做自由職業者。*

衷心感謝以下技術專家對本文的審閱,並提供有價值的回饋:明芳 (施耐德電氣) 和Jason年輕 (Microsoft)
明芳 (施耐德電氣) 是由施耐德電氣的傑出發展經理。
Jason年輕 (微軟) 是高級專案經理,微軟 DX 和 MS Dev 秀共同主辦 (msdevshow.com)