開發架構
1. ORM, LLBL Gen,NHibernate
2. 介面與實現分離,介面與邏輯分離,分五個項目,
BusinessLogic, Interface,Manager,Validation,EntryForm
3. SQL與ORM
4. 通訊整合 Remoting/WCF
5. Control/Component: NumberiEditor,TextEditor,Grid,ComboBox,ListBox,ListView,Tree
6. 異常
7. 中繼資料
ORM
使用ORM可以減少大量的資料讀寫和綁定代碼,做大型的項目,必須用ORM
再配合CodeSmith代碼產生器,可以完成資料讀寫90%的代碼。
介面與邏輯分離
做一個MIS的庫存項目,有四個項目
BusinessLogic 商務邏輯,業務實體
Interface 介面
Manager 實現介面
System Administration/Inventory, 介面
這樣達到的效果,
1. 資料表新增加欄位,介面部分不需要任何改動;
2. 可以靈活的切換介面到WPF/ASP.NET/Sliverlight
3. 外掛程式式Addon,PlugIn式的開發,新增加功能,不需要改動原有的專案檔
SQL與ORM
ORM是跨平台的,要相容所有的主流資料庫,必需建立一種文法,以達到讀寫各種類型的資料庫。
熟悉這個映射表,可以很快的入門,寫出讀寫資料代碼。雖然這個步驟不是必須的(因為CodeSmith代碼產生器會成90%的代碼)。 再配合SQL解析工具,輸入SQL語句,公用程式(SQLTranslate.exe)可以自動翻譯SQL為ORM的寫法。
如果擔憂ORM效能不好,可以直接使用ADO.NET
這個寫法需要工具的配合,才能快速開發.
這個代碼產生器也是組合的方式,例如表名是backupset
Entity 實體 |
BackupSet |
ADO.NET(Get,Save,Insert,Update,GetList) |
BackupSetDAL |
Interface 介面 |
IBackupSet |
Service 邏輯調用 |
BackupSetService |
ASP.NET應用代碼產生器介面如下,配和ADO.NET或是Enterprise Library,具有很強的威力。
最新版本的ASP.NET應用代碼產生器,直接寫成CodeSmith的模板。這樣,在改動產生的程式碼時,不需要任何編譯動作。
CodeSmith現有版本只支援.NET 2.0,不支援.NET 3.5和.NET 4.0, 雖然CodeSmith 6.0 Alpha已經釋出,但是非常的不stable.
也沒有Studio可以使用。
SQL Profiler 跟蹤查詢
直接運行SQL Profile
運行自己開發的SQL Profiler
啟動程式中增加配置節
<system.diagnostics>
<!-- LLBLGen Trace
Trace Level: 0 - Disabled
3 - Info
4 - Verbose
-->
<switches>
<add name="SqlServerDQE" value="4" />
<add name="ORMGeneral" value="0" />
<add name="ORMStateManagement" value="0" />
<add name="ORMPersistenceExecution" value="0" />
</switches>
<trace autoflush="true">
<listeners>
<add name="socketWriterTraceListener"
type="Avatar.ORMTraceListener,ORMTraceListener" />
</listeners>
</trace>
</system.diagnostics>
開啟監聽程式
原始碼如下
或者運行如下的跟蹤程式
改進的智能提示支援
當滑鼠移至上方在實體名上時,可以顯示實體對應的表名
當滑鼠移至上方在欄位上時,可以顯示欄位對應的表名
在SQL查詢管理器中,當滑鼠移至上方在表名上時,可以顯示表的注釋
建立表的描述
建立欄位的描述
匯入表中現有的欄位描述,以達到最小的勞動量
智能提示的設計演化過程
1. 把提示內容放到Access資料庫中,這樣,拷貝到項目開發目錄中即可。遇到Provider=Microsoft.Jet.OLEDB.4.0 沒有64bit的版本,編譯時間必須設定x86的平台格式,而不是AnyCPU.
增加Provider=Microsoft.ACE.OLEDB.12.0,但是,在每台開發人員機器上安裝這個組件,不太實現。
2. 使用SQLExpress, 這種方式的問題,還是需要配置SQL,可嘗試用dbo4之類的對象資料庫,一個檔案拷貝到指定目錄就可以(可行, doable)
3. SQL Server內建實現方式,如
開啟SQL Profiler, 秘密就在預存程序sp_addextendedproperty
最後,乾脆做一個工具,專門用於更新欄位的描述,這樣會方便很多。
Remoting/WCF通訊技術
功能目標
1. 應用程式伺服器 Remoting/WCF Server
2. Report Server
3. Workflow Server
4. 並發使用者控制,追蹤記錄檔輸出(Trace output),組件授權驗證
License 許可控制
用RSA簽名xml檔案,產生不可修改的xml檔案,以保護軟體授權許可
與硬體(CPU,Harddisk)資訊綁定,在產生license檔案時,先要求使用者運行一段公用程式,產生一個hardware的sinature的檔案,license generator依據這個檔案產生許可檔案。
與軟體綁定,比如示範版不允許資料庫超過2G的容量大小(SQL Express規定資料庫大小不能超過4G);只能在規定的時間內運行,通常是一個月,到期後軟體無法啟動;不允許在虛擬機器(Virtual Machine)中運行,因為虛擬機器的原因,整個系統可以無限制的被Ghost還原;
Report Extension
經典的SQL查詢語句的寫法是這樣,可以製作出客戶報表
現在我們換成這樣的查詢資料庫的寫法
2種方式,SQL Procedure和.NET Assembly,可維護性肯定後者強於前者,效能的損失也有.
後者也只有程式員可以維護報表,客戶不可能懂.NET.
但是,面對日益複雜的商務邏輯,多資料庫需求的客戶(有的客戶指定要用Oracle),用.NET Assembly應該是一種趨勢。
資料庫管理
一個架構資料庫,驅動多個業務資料庫。
一個業務資料庫可以看成一套帳,可以獨立進行版本管理,功能控制;也可以針對不同的客戶需要,定製(customization)。
如下的註冊公司的介面,Driver Assembly和Driver Type即是註冊客戶定製的程式集,以達到同一個產品,維護多個客戶,不同行業的客戶的使用。
效能(Reflection)的損失是不可避免的,同時也帶來相當可觀的靈活性。
Microsoft的產品也經常Reflection,為什麼我們不可以,為一點斤斤計較的Performance?
認證authentication,授權authorization 模式(AD/Forms/Windows)
因為我們已經設計出了Application Server,所以,這個地方可以為所欲為,盡情的發揮。
看K3的登陸方式
Activity Directory的方式,是推薦的企業區域網路構建方法,AD帶來的PC間相互信任的關係,好處簡直讓人不可忘卻。
Forms方式,可以對使用者名稱和密碼進行加密,可以記住使用者名稱和密碼,定期要求使用者修改密碼
Reporting Services的預設登陸方式是Windows,我們需要把它重寫成Forms
很遺憾,即使是Microsoft SQL Server 2008 R2,仍然需要手動修改設定檔,以改成Forms認證。計劃中,要製造一個小工具,來修改Reporting Services的認證方式,手動的配置有些複雜,容易出錯。
再來看整合到ERP中的Report Manager的登陸方式
再來看一下授權,三種許可權:功能許可權,欄位許可權,資料許可權
功能許可權, 基於角色的認證授權 對各子系統的功能模組的執行許可權
先設定使用者組別許可權
再到使用者註冊時,設定使用者所屬的組別
可實現ERP系統中60%的許可權需求。
欄位許可權也實現,如,Demo使用者不可以訪問所有的報表,但是可以讀取所有的客戶和供應商資訊。
欄位許可權對某些特殊的欄位進行控制,如倉庫人員不可以看到採購員輸入的物料單價,A銷售人員,不可以看到B銷售人員的客戶的連絡方式,
資料許可權,是對具體資料的操作許可權。
比如,當採購金額達到10萬時,財務經理Finance Manager不可以直接修改;
於是做出一個資料許可權編輯器
中顯示的條件,採購單總金額大於1000000,費用大於5000,而且供應商為Maskey.
這個條件是可以動態增加和刪除,在運行時,由運算式引擎負責解析運算式,傳回運算式執行的結果。
異常處理
在業務系統中,異常可實現N層撤消復原的能力。
為了不暴露具體的產品實現細節,異常的顯示方式,設計如下的異常對話方塊。
實現方式是註冊當前應用程式定義域的UnhandledException事件,將異常顯示在自訂對話方塊中。
AppDomain.CurrentDomain.UnhandledException+= new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
觀察一下Microsoft的產品對異常出錯的提示,Microsoft Report Builder
Microsoft SQL Server
SQL Server出錯表單的左下方,有三個按鈕,Help,Copy message text, Show technical details
Show technical details會開啟一個stack trace的表單,用於診斷出錯的細節資訊。
異常的傳送實現,有二個思路
1. 運用Enterprise Library的Log Application Block,將異常重新導向的各種輸出設定中(Console,File,Database)
2. 使用TCP Socket技術,將異常發往指定的伺服器,並記錄使用者的操作步驟。因為已經製作出了Application Server,所以,這個地方實現起來也很簡單。至於發送出錯時,當前的操作使用者名稱稱,stack資訊,甚至可以copy screen,把當前出錯的螢幕圖片也一同發送到伺服器指定目錄中。
應用程式框架代碼,將會大量使用.NET Trace機制,將架構的運行狀態輸出
Public class SQLServerTraceListener : TraceListener {
public override void Write(string message)
{
using (SqlConnection conn =
new SqlConnection("server=(local);database=TraceDatabase;Integrated security=true;")) {
using (SqlCommand cmd = conn.CreateCommand()) {
cmd.CommandText = "INSERT INTO Logs(Message) VALUES(@message)";
cmd.Parameters.Add(new SqlParameter("@message", message));
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
}
public override void WriteLine(string message)
{
Write(message);
}
}
這樣讀寫SQL會導致Performance下降,推薦的方式是TCP Socket技術,把異常發送到伺服器(Application Server),大量的異常,是不需要處理的,比如,使用者登入時輸錯密碼,沒有必要大量的寫到伺服器的資料庫中。
架構代碼可以識別哪些是關鍵代碼出錯,這些異常則很有必要記錄到持久化介質中以供開發人員診斷。
中繼資料管理
Schema Viewer ERP維護人員最關心的資料表欄位,到底存放了一些什麼內容,資料間的關係
資料間關係
.NET 屬性代碼
看到,已經將Table Name放到了Xml注釋的summary中,這樣,充分利用.NET智能感知。
架構資料庫,還有大量的中繼資料管理:Report, Lookup,Query, Workflow,Form Layout,User/User Group