本文章是由機器翻譯。

技術最前線

查詢服務

Dino Esposito

Dino Esposito天色更常見的公司,使其作為平原老 HTTP 端點的後端業務服務。這種類型的建築要求沒有有關資料庫和物理資料模型的資訊。用戶端應用程式,甚至不需要對特定于資料庫的庫 (如Entity Framework的引用。服務的物理位置無關,您可以將後端上處所保持或透明地遷移到雲。

作為解決方案架構師或開發人員主管,有兩種情況下,你應該準備好去面對時採取這一策略。第一個是當你沒有獲得任何服務的內部運作。在這種情況下,你不是即使在條件的要求更多或更少的資料來微調您的用戶端應用程式的性能。

第二種情況是當你還負責主­泰甯這些後端服務,並可影響一定程度上的公共 API。在這篇文章中,我將重點主要在後一種情況。我將討論具體的技術以靈活的方式實現可查詢服務的作用。我將使用的技術是ASP.NETWeb API OData 服務。幾乎一切在這篇文章討論了適用于現有的ASP.NET平臺和ASP.NET5 vNext,以及。

密封後端服務

在進入之前可查詢服務設計,我將簡要探討,你有沒有控制可用的服務,第一種方案。你給您需要對這些服務進行調用,但沒有辦法修改的數量和形狀的反應的所有詳細資訊。

這種密封的服務被密封的原因。他們是一部分官員的它尾到貴公司。這些服務是整體結構的一部分,並不打算改變下無憂無慮。由於更多的用戶端應用程式依賴于這些服務,很可能你的公司正在考慮版本控制。一般來說,雖然,必須有一個令人信服的理由實施任何新發佈的這些服務之前。

如果密封的 API 是一個正在開發的用戶端應用程式的問題,你可以做的唯一事情是包裹在一個額外的代理層原有服務。然後,您可以使用任何的技巧,實現你的目的,包括緩存資料的新聚合和插入額外的資料。從建築的角度看,由此而設置的服務,然後從域的基礎結構層轉移服務層。它甚至可能在應用程式層高 (見圖 1)。

從密封服務更靈活的應用程式服務
圖 1 從密封服務更靈活的應用程式服務

讀側的 API

現代 Web 應用程式都是圍繞一個內部 API。在某些情況下,此 API 成為公共。值得考慮那ASP.NET5 vNext 推一種體系結構,其中ASP.NETMVC 和剃刀引擎為生成的 HTML 視圖提供必要的基礎設施。

ASP.NETWeb API 表示用於處理用戶端請求來自用戶端的瀏覽器和 HTML 頁以外的其他的理想的基礎設施。換句話說,一個新的ASP.NET網站理想情況下設計作為 HTML 圍繞後端服務可能密封套一層薄薄的了。團隊負責 Web 應用程式,不過,現在也是擁有者的後端的 API,而不是消費者。如果任何人有問題,你會聽到他的投訴或提出意見建議。

多數消費者 API 問題涉及的數量和品質的返回的資料。查詢 API 的端的是通常最棘手的問題創建,因為你永遠不知道它正在您的資料的方式要求和用於從長遠來看。命令 API 的端的是通常穩定得多,因為它取決於業務領域和服務。功能變數名稱服務有時會發生變化,但至少他們保持不同,往往速度較慢的步伐。

通常情況下,你有一個模型背後的 API。API 查詢方面往往以反映模型 API 是否休息或 RPC 風味。最終,一個閱讀 API 的痛點是它返回的資料和資料集合,它支援的格式。這一問題有一個友好的名稱 — — 資料傳輸物件 (Dto)。

當您創建 API 服務時,生成從現有的資料模型並暴露在外面的世界,通過相同的本機或自訂模型。多年來,軟體架構師設計應用程式以自底向上的方式。他們總是開始從底部通常關係資料模型。這種模式旅行到展示層。

根據不同的用戶端應用程式的需要,一些 DTO 類創建一路走來確保演示文稿可以處理的正確格式正確的資料。越來越大的作用,用戶端應用程式的作用下,今天改變了這方面的軟體架構及開發。而建設一個後端的 API 的命令一邊仍是一個相對容易的工作,制定一個單一操作且通常足以資料模型,適合所有可能的用戶端是一個困難得多的工作。閱讀 API 的靈活性在今天是制勝的因素,因為你永遠不知道哪種用戶端應用程式,您的 API 將永遠的臉。

查詢服務

在最新版的書中,"Microsoft.NET:構建企業應用程式"(微軟出版社,2014年),Andrea Saltarello 和我正式確定一個我們稱之為階層式運算式目錄樹 (讓) 的概念。讓背後的想法是應用程式層和域服務交換 IQueryable < T > 盡可能的物件。這通常發生每當層住在相同的進程空間,不需要序列化。通過交換 IQueryable < T >,您可以推遲任何所需的查詢結果從篩選器的組成和資料投影到最後一刻。您可以在每個應用程式的基礎,而不是域級 API 一些硬編碼形式適應這些。

讓思想走在手與新興 CQRS 模式。這從命令堆疊推讀取堆疊的分離。圖 2 說明您的體系結構讓模式和一堆可查詢服務的點。

可查詢物件都是在最後一分鐘查詢
圖 2 可查詢物件都是在最後一分鐘查詢

讓的主要好處是你不需要任何的 Dto 在層中傳送資料。你仍然需要有視圖模型類在某種程度上,但那是一個不同的故事。你必須處理視圖模型類,只要你有一個使用者介面,以便用資料填充。視圖模型類表達您的使用者期望的佈局所需的資料。這是唯一一套的你要的 DTO 類。一切都從你身體上查詢資料和最多早餐通過 IQueryable 引用的水準。

讓和查詢服務的另一個好處是生成查詢應用程式級別的查詢。他們的邏輯,緊依域專家語言。這使得它容易要求映射到代碼和與客戶討論所謂的錯誤或誤解。大多數情況下,快速查看一下代碼可以説明您對邏輯加以解釋。作為一個例子,這裡是一個讓查詢可能看起來像:

var model = from i in db.Invoices
                        .ForBusinessUnit(buId)
                        .UnpaidInLast(30.Days)
  orderby i.PaymentDueDate
  select new UnpaidViewModel
    {
      ...
    };

從Entity Framework根物件的資料庫上下文,您為所有入站發票查詢並選擇那些相關者給定的業務單位。當中,你發現那些仍然未付的天數過去到期的條款。

高興的是 IQueryable 的引用是不真實的資料。只有當你換一些 IList IQueryable,針對資料來源執行查詢。篩選器添加一路上只是條款添加到實際的查詢正在運行某一時刻的位置。只要你在相同的進程空間,轉移和保存在記憶體中的資料量是最低限度的規定。

這種影響可擴充性如何?VNext 平臺進行了優化的新興趨勢是您保持您的網站後端盡可能緊湊。理想情況下,它將單個層。您通過複製通過微軟 Azure Web 角色的各種獨特的層實現的可擴充性。具有單個 Web 後端層允許您使用 IQueryable 無處不在和救自己 DTO 類群。

執行查詢服務

在以前的代碼片段中,我假定你的服務被實現為一層周圍一些Entity Framework資料庫上下文。這只是例子,雖然。你也完全可以封裝在ASP.NETWeb API 立下的實際資料提供程式。這樣一來,你有表示域服務功能的 API 的好處,仍然能夠通過 HTTP,因此解耦用戶端從一個特定的平臺和技術。

然後您可以創建一個 Web API 類庫和主辦一些ASP.NETMVC 網站、 Windows 服務或甚至某些自訂宿主應用程式中。在 Web API 專案中,您創建從 ApiController 派生的控制器類和公開返回 IQueryable < T > 的方法。最後,你裝飾每個 IQueryable 方法使用 EnableQuery 屬性。現在已經過時的查詢屬性以及工作。這裡的關鍵因素是 EnableQuery 屬性允許您追加到請求的 URL 的 OData 查詢 — — 就像這樣:

[EnableQuery]
public IQueryable<Customer> Get()
{
  return (from c in db.Customers select c);
}

這基本段代碼表示您的 API 的心跳。它本身不返回任何資料。它可以讓客戶塑造了他們想要的任何返回的資料。看看在代碼圖 3 ,認為它是一個用戶端應用程式中的代碼。

圖 3 用戶端應用程式可以塑造返回的資料

var api = "api/customers?$select=LastName";
var request = new HttpRequestMessage()
{
  RequestUri = new Uri(api)),
    Method = HttpMethod.Get,
};
var client = new HttpClient();
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
  var list = await
    response.Content.ReadAsAsync<IEnumerable<Customer>>();
  // Build view model object here
}

在 URL 中的 $select 公約確定資料投影用戶端接收。你可以使用 OData 查詢語法的力量來塑造了查詢。如果要想瞭解更多此類資訊,請參閱 bit.ly/15PVBXv

例如,一個用戶端可以只請求小列的子集。另一個用戶端或不同的螢幕,在相同的用戶端可以查詢一塊較大的資料。這一切會發生沒有感人的 API 和創建 Dto 沿途噸。你需要的就是 OData 查詢 Web API 服務和最終視圖模型類,要消耗。傳輸的資料是減至最低,只篩選的欄位返回的。

有幾個顯著方面。首先,OData 是一個詳細的協定,否則不能給它起的作用。這意味著,當您應用 $select 投影,JSON 有效載荷將仍然列出原始 IQueryable < T > 中的所有欄位 (Get 方法中的原始客戶類的所有欄位)。然而,只有指定的欄位將舉行一個值。

另一個要考慮的一點是區分大小寫。這會影響您使用向查詢中添加一個 WHERE 子句的 $filter 查詢元素。你可能想要聯絡或致電 tolower toupper OData 功能 (如果您正在使用 OData 用戶端庫支援) 實現正常化字串之間的比較。

總結

坦白地說,我從來沒有覺得 OData 是值得認真考慮的直到我發現自己 — — 作為一個後端的 API 的擁有者 — — 在風暴中的不同的 Dto,從相同的資料模型返回的請求。每個請求似乎合法和放置的一個非常崇高的事業 — — 性能的改善。

在某種程度上,似乎想要做的所有這些客戶機被"查詢"在很多的後端以同樣的方式,他們會質疑常規資料庫表。然後我更新後端服務來公開 OData 端點,從而使每個用戶端下載只有它們在感興趣的欄位的靈活性。

類型 T 的每個 IQueryable 方法是關鍵。它可能會或可能不是同一類型 T 你在物理模型。它可以與普通資料庫表匹配或源于對客戶做伺服器端和透明的資料聚合。OData 應用時,雖然,你讓客戶查詢資料集的一個已知的單一實體,T,所以為什麼不試一試嗎?


Dino Esposito 的作者之一"Microsoft.NET:構建企業應用程式"(微軟出版社,2014年) 和"程式設計ASP.NETMVC 5"(微軟出版社,2014年)。Microsoft.NET 框架和 Android 平臺,它也會經常在世界各地的業內活動中發表演講的技術傳教士,埃斯波西托分享他視覺軟體 software2cents.wordpress.com 和在 Twitter 上 twitter.com/despos

感謝以下技術專家對本文的審閱:喬恩 Arne Saeteras