.NET應用架構設計—面向查詢服務的參數化查詢設計(分解業務點,單獨配置各自的數據查詢契約)

閱讀目錄:編程

  • 1.背景介紹
  • 2.對業務功能點進行邏輯劃分(如:A、B、C分別三個業務點)
    • 2.1.配置映射關係,對業務點配置查詢契約(構造VS插件方便生成查詢契約)
    • 2.2.將配置好的映射策略文件放在調用端,與服務不耦合
  • 3.Dynamic、Dom動態構造服務端對象(Dynamic、DOM實現動態DOM)

1.背景介紹

如今愈來愈多的公司都在嘗試SOA架構的實踐,本人最近也在嘗試學習這方面的技術,可是在實踐過程當中遇到一個問題,我想這個問題也是咱們廣泛實踐者都應該會遇到的問題,問題描述以下:架構

咱們有一個SOA商品(Item)查詢接口,這個接口很通用,主要用來支撐平常不少其餘系統的大量關於Item的查詢,尤爲是在高峯期間該服務的壓力是很大的;咱們站在SOA的角度看這個接口,這個通用的接口解決了衆多的查詢業務,確實不錯,可是咱們切換一下角度,站在每個調用接口的訪問端看彷佛並非很滿意或者說犧牲了部分性能上的代價,由於咱們沒法乾淨利落的只獲取當前這個業務點須要的數據項;這個Item服務接口所返回的數據項必須同時知足全部調用它的業務點,哪怕此次調用我只須要用到Item的三分之一的數據字段都不行,每次都會把不須要的字段都查詢出來,不論是返回的性能、查詢的性能,其實都是能夠經過調整設計來避免的;框架

(查看大圖)ide

以往咱們的思路都是集中在服務端,常規作法都是提供了一個可以容納全部查詢客戶端需求的數據實體,客戶端可選擇的餘地頗有限,沒法只獲取本身所須要的幾個數據項,甚至各個業務點在不一樣的狀況下都有可能須要兩到三個數據返回實體;總而言之,面向數據查詢的服務接口若是要向着SOA方向發展那就必須包含SOA設計上的相關原則,如這裏的面向查詢爲主的服務設計其實就是缺乏SOA原則中的」服務應具備策略性「一原則;工具

爲何以往一直沒有暴露出這個問題呢,是由於以往都是在本地直接調用「查詢引擎」,如:SQLSERVER,在「查詢引擎」的最後一層就是應用程序,而應用程序中能夠編寫不少彼此相似的查詢方法,每一個方法可能只有一兩個字段的差別性,或者經過「企業應用架構模式—查詢對象模式」來將不一樣的方法合在一塊兒經過一個能夠調整查詢字段的對象來配置本次須要的查詢字段;因爲如今咱們已將查詢服務化,就不太可能再去爲了全部客戶端在去適應性的去擴充相似沒有太大價值的接口,可是客戶端又須要將本身所須要的查詢字段讓服務知道,因此這裏的解決方案能夠稱爲面向SOA的」企業應用架構模式—查詢對象模式「性能

本文將經過運用」關注點分離「通用設計思想來對查詢服務在服務端的強耦合進行分解,將強耦合從服務端遷移出來經過策略性的配置將關注點放入各自的客戶端,從而有效的解決服務再也不臃腫的問題,若是理解上有困難能夠嘗試使用面向SOA的」企業應用架構模式—查詢對象模式「概念來理解;學習

2.對業務功能點進行邏輯劃分(如:A、B、C分別三個業務點)

首先咱們須要將相對於服務來講的客戶端中全部業務點進行邏輯劃分,將本來一個高耦合的龐大數據實體分解成各自所須要的一個精簡的數據實體;業務點的劃分目地在於能夠將數據實體能與之對應起來,這個數據實體是針對於查詢服務而言的,對於客戶端來講沒有任何的依賴和約束,也就是說本次業務點發起的查詢將把這個數據實體轉化成一組查詢策略中的設置帶到服務端中,而後服務端在根據這組策略信息進行組合最終的查詢語句;大數據

注:這裏的數據實體並非服務端定義的DTO,也不是客戶端定義的DTO,而是一個只跟本次業務查詢相關的數據查詢實體,該實體不是一個定義的類,而是一個策略,相似:spa

A.Business{Query field{ItemNumber、Description、PromationPrice}} 插件

這樣一組配置信息;客戶端用來反序列化的DTO能夠是一個龐大的共用的數據實體,也能夠是跟業務點綁定的精簡實體,對於查詢沒有任何影響,咱們要解決的是「只查詢我所須要的數據項,只返回我所須要的數據項」,而跟你在服務端、客戶端定義的用來輔助序列化的實體沒有任何關係;

 (查看大圖)

將查詢的字段、返回的字段經過查詢策略帶入到服務端,咱們就可以知道本次業務點查詢的是須要什麼樣的字段,而後就能夠在構造查詢引擎參數時將返回的字段直接加上或者過濾不須要的;

2.1.配置映射關係,對業務點配置查詢契約(構造VS插件方便生成查詢契約)

將系統中須要調用服務接口的全部功能點進行業務點邏輯劃分設計後,每一個業務點都須要在本身發起調用服務的時候可以帶上在以前某個時間點設計好的查詢契約,這個用來生成查詢契約的工具最好是集成在VisualStudio中的自定義插件,在設計時用來動態構造一個對應的契約配置文件,若是能夠的話能夠採用動態代碼方案,將配置文件的靜態文件經過動態生成代碼的方式嵌入到生成的代碼中去,減小不須要的配置文件,也減小查詢框架的性能開銷,一次生成後就能夠直接使用;

2.2.將配置好的映射策略文件放在調用端,與服務不耦合

本篇文章的解決方案最大的突破點就是將關注點從服務端轉移到全部客戶端上,將本來都集中在服務上的全部客戶端的需求分離出去,每一個須要調用服務的客戶端維護好本身的一份查詢契約,在每次調用服務的時候帶上那份契約;若是處於性能考慮每次帶上契約會增長開銷,那麼能夠在第一次身份驗證的時候在服務上確認,之後調用都忽略;

這樣一來服務將精簡不少,經過一樣的設計方法能夠用來設計不少相似的服務接口,將關注點從服務上轉移到客戶端上,會是一個很好的設計思路;

3.Dynamic、Dom動態構造服務端對象(Dynamic、DOM實現動態DOM)

藉助C#新特性Dynamic,咱們能夠在.NET平臺上進行動態編程,這裏能夠解決咱們預先定義服務端實體的好處;以往咱們須要在服務上定義一個至少能容納全部客戶端查詢契約中的全部數據項的實體,可是當咱們運用動態編程時,咱們無需事先定義一個類,而能夠在運行時動態獲取對象屬性,固然這得益於.NETDLR的實現;再適當的結合DOM思想,咱們就能夠實現一個動態DOM效果,對於DOM的某個Element的訪問也無需定義映射實體而後在經過屬性獲取,中間既增長了序列化的開銷還增長了開發工做量;

 1 using System;
 2 using System.Collections.Generic; 
 3 
 4 namespace ConsoleApplication1.DynamicDom
 5 {
 6     public class ItemEntity : System.Dynamic.DynamicObject
 7     {
 8         /// <summary>
 9         /// 可使用LINQ TO XML或者將XML數據構造在一個指定的容器中,用來判斷是否存在
10         /// </summary>
11         private static Dictionary<string, object> itemPropery = new Dictionary<string, object>();
12         static ItemEntity()
13         {
14             itemPropery.Add("ItemNumber", 1029394);
15             itemPropery.Add("PromationPrice", 100);
16         }
17         public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
18         {
19             if (itemPropery.ContainsKey(binder.Name))
20             {
21                 result = itemPropery[binder.Name];
22                 return true;
23             }
24             result = null;
25             return false;
26         }
27     }
28 } 
1 dynamic itemEntity = new DynamicDom.ItemEntity();
2 Console.WriteLine("ItemNumber:" + itemEntity.ItemNumber);
3 Console.WriteLine("PromationPrice:" + itemEntity.PromationPrice);
4 Console.ReadLine(); 

這裏只是一個簡單的示例,目的是想讓並不太瞭解Dynamic的朋友有了直觀上的認識;經過使用Dynamic、Dom能夠在服務端上無需定義任何的實體,根據各個客戶端傳過來的配置直接進行動態訪問,能夠藉助LIQN TO XML;

全文僅僅是一個設計上的介紹,要想徹底實現上面這些效果須要仍是須要開發些東西的,這裏只是拋磚引玉,但願對正在設計相關內容的朋友提供一個思路;

相關文章
相關標籤/搜索