iT邦幫忙

DAY 27
2

Kuick Application & ORM Framework系列 第 27

Kuick -- 遮斷器 Interceptor

Kuick 在資料層裡,針對任何 Entity 的 Select, Insert, Update, Delete, ExecuteNonQuery, ExecuteQuery, ExecuteScalar, ExecuteStoredProcedure 方法,提供管道給專案程式安插自定義的處理區段,Interceptor 是 Entity 事件的變型,設計時點不同,控管範圍更廣。

<何時附加遮斷器>
僅允許在系統啟動前 (PreStart) 的階段,進行附加遮斷器,關於系統啟動的事件,請參考前文『Kuick -- 你聽得到系統的心跳聲嗎?』的說明。

<如何附加遮斷器>
Kuick.Data.Interceptor 類別,提供附加 12 種遮斷器的靜態 (static) 方法:
01. AttachBeforeSelect -- 附加『選取前』遮斷器
代理方法取得選取前 Sql 物件,依據專案需求增修選取條件。

02. BeforeInsert -- 附加『新增前』遮斷器
代理方法取得新增前 Entity 物件,依據專案需求調整待儲存資料。

03. BeforeUpdate -- 附加『修改前』遮斷器
代理方法取得修改前 Entity 物件,依據專案需求調整待修改資料。

04. BeforeDelete -- 附加『刪除前』遮斷器
代理方法取得刪除前 Entity 物件,依據專案需求調整待刪除資料。

05. BeforeExecuteNonQuery -- 附加『執行非查詢指令前』遮斷器
代理方法取得非查詢前指令 (Sql Command) 與參數集合 (IDbDataParameter[]),依據專案需求調整指令與參數。

06. BeforeExecuteQuery -- 附加『執行查詢指令前』遮斷器
代理方法取得查詢前指令 (Sql Command) 與參數集合 (IDbDataParameter[]),依據專案需求調整指令與參數。

07. BeforeExecuteScalar -- 附加『執行查詢單值前』遮斷器
代理方法取得查詢單值前指令 (Sql Command) 與參數集合 (IDbDataParameter[]),依據專案需求調整指令與參數。

08. BeforeExecuteStoredProcedure -- 附加『執行預儲程序前』遮斷器
代理方法取得預儲程序前指令 (Stored Procedure) 與參數集合 (IDbDataParameter[]),依據專案需求調整指令與參數。

09. AfterSelect -- 附加『選取後』遮斷器
代理方法取得選取後 Entity 物件,依據專案需求調整待回傳資料。

10. AfterInsert -- 附加『新增後』遮斷器
代理方法取得新增後 Entity 物件與結果 (Result),依據專案需求調整待回傳資料。

11. AfterUpdate -- 附加『修改後』遮斷器
代理方法取得修改後 Entity 物件與結果 (Result),依據專案需求調整待回傳資料。

12. AfterDelete -- 附加『刪除後』遮斷器
代理方法取得刪除後 Entity 物件與結果 (Result),依據專案需求調整待回傳資料。

// 01. AttachBeforeSelect -- 附加『選取前』遮斷器
// 遮斷所有 Entity
AttachBeforeSelect(string entityName, Action<string, Sql> action)
// 遮斷特定 Entity
AttachBeforeSelect<T>(Action<string, Sql> action)where T : IEntity

// 02. BeforeInsert -- 附加『新增前』遮斷器
// 遮斷所有 Entity
AttachBeforeInsert(string entityName, Action<string, IEntity> action)
// 遮斷特定 Entity
AttachBeforeInsert<T>(Action<string, T> action)where T : IEntity

// 03. BeforeUpdate -- 附加『修改前』遮斷器
// 遮斷所有 Entity
AttachBeforeUpdate(string entityName, Action<string, IEntity> action)
// 遮斷特定 Entity
AttachBeforeUpdate<T>(Action<string, T> action)where T : IEntity

// 04. BeforeDelete -- 附加『刪除前』遮斷器
// 遮斷所有 Entity
AttachBeforeDelete(string entityName, Action<string, IEntity> action)
// 遮斷特定 Entity
AttachBeforeDelete<T>(Action<string, T> action)where T : IEntity

// 05. BeforeExecuteNonQuery -- 附加『執行非查詢指令前』遮斷器
// 遮斷所有 Entity
AttachBeforeExecuteNonQuery(string entityName, Action<string, string, IDbDataParameter[]> action)
// 遮斷特定 Entity
AttachBeforeExecuteNonQuery<T>(Action<string, string, IDbDataParameter[]> action)where T : IEntity

// 06. BeforeExecuteQuery -- 附加『執行查詢指令前』遮斷器
// 遮斷所有 Entity
AttachBeforeExecuteQuery(string entityName, Action<string, string, IDbDataParameter[]> action)
// 遮斷特定 Entity
AttachBeforeExecuteQuery<T>(Action<string, string, IDbDataParameter[]> action)where T : IEntity

// 07. BeforeExecuteScalar -- 附加『執行查詢單值前』遮斷器
// 遮斷所有 Entity
AttachBeforeExecuteScalar(string entityName, Action<string, string, IDbDataParameter[]> action)
// 遮斷特定 Entity
AttachBeforeExecuteScalar<T>(Action<string, string, IDbDataParameter[]> action)where T : IEntity

// 08. BeforeExecuteStoredProcedure -- 附加『執行預儲程序前』遮斷器
// 遮斷所有 Entity
AttachBeforeExecuteStoredProcedure(string entityName, Action<string, string, IDbDataParameter[]> action)
// 遮斷特定 Entity
AttachBeforeExecuteStoredProcedure<T>(Action<string, string, IDbDataParameter[]> action)where T : IEntity

// 09. AfterSelect -- 附加『選取後』遮斷器
// 遮斷所有 Entity
AttachAfterSelect(string entityName, Action<string, Sql, IEntity> action)
// 遮斷特定 Entity
AttachAfterSelect<T>(Action<string, Sql, T> action)where T : IEntity

// 10. AfterInsert -- 附加『新增後』遮斷器
// 遮斷所有 Entity
AttachAfterInsert(string entityName, Action<string, IEntity, Result> action)
// 遮斷特定 Entity
AttachAfterInsert<T>(Action<string, T, Result> action)where T : IEntity

// 11. AfterUpdate -- 附加『修改後』遮斷器
// 遮斷所有 Entity
AttachAfterUpdate(string entityName, Action<string, IEntity, Result> action)
// 遮斷特定 Entity
AttachAfterUpdate<T>(Action<string, T, Result> action)where T : IEntity

// 12. AfterDelete -- 附加『刪除後』遮斷器
// 遮斷所有 Entity
AttachAfterDelete(string entityName, Action<string, IEntity, Result> action)
// 遮斷特定 Entity
AttachAfterDelete<T>(Action<string, T, Result> action)where T : IEntity

請參考 MSDN 針對 Action Delegate, Func<TResult> Delegate 的說明

<遮斷器如何觸發執行>
遮斷器由 Api 裡的不同方法觸發:
01. Api.Query ------------------- Interceptor: OnBeforeSelect, OnAfterSelect
02. Api.AggregateQuery ---------- Interceptor: OnBeforeSelect
03. Api.DistinctQuery ----------- Interceptor: OnBeforeSelect
04. Api.DistinctDateQuery ------- Interceptor: OnBeforeSelect
05. Api.Count ------------------- Interceptor: OnBeforeSelect
06. Api.Add --------------------- Interceptor: OnBeforeInsert, OnAfterInsert
07. Api.Modify ------------------ Interceptor: OnBeforeUpdate, OnAfterUpdate
08. Api.Remove ------------------ Interceptor: OnBeforeDelete, OnAfterDelete
09. Api.ExecuteNonQuery --------- Interceptor: OnBeforeExecuteNonQuery
10. Api.ExecuteQuery ------------ Interceptor: OnBeforeExecuteQuery
11. Api.ExecuteStoredProcedure -- Interceptor: OnBeforeExecuteStoredProcedure
12. Api.ExecuteScalar ----------- Interceptor: OnBeforeExecuteScalar

<實作重點>

  1. 透過 Application Framework 確保遮斷器在系統進行任何資料操作前,已經完成附加。
  2. 提供設計期已知要進行遮斷的 Entity,以及執行期再判斷的雙重方法。
  3. 遮斷代理方法轉型特殊處理,這部份請參考 Kuick.Interceptor.ActionTransfer<T> 方法,這點相當重要,如果想要自行實作相關功能,請細看。

<範例>
在任何專案建立實作 IStart 介面的類別,在 DoPreStart 方法裡加上適當的 Interceptor 設定,下面的例子對於資料處理進行 2 項遮斷設定:
1. UserEntity 新增前,Actived 欄位值一律改成 true。
2. 所有資料刪除發生錯誤時,記下錯誤 log,如果資料正確刪除而且是是刪除會員資料,額外寄發通知信。

using System;
using Kuick;
using Kuick.Data;

namespace KuickSample
{
	public class SampleStart : IStart
	{
		public void DoPreStart(object sender, EventArgs e)
		{
			// BeforeInsert -- 附加『新增前』遮斷器
			Interceptor.AttachBeforeInsert<UserEntity>((entityName, user) => {
				user.Actived = true;
			});

			// AfterDelete -- 附加『刪除後』遮斷器
			Interceptor.AttachAfterDelete<IEntity>((entityName, instance, result) => {
				if(!result.Success) {
					// 資料刪除錯誤
					Logger.Error(
						"資料刪除錯誤",
						new Any("entityName", entityName),
						new Any("keyValue", instance.KeyValue)
					);
				} else {
					// 資料刪除正確
					if(entityName == typeof(UserEntity).Name) {
						UserEntity user = instance as UserEntity;
						if(null != user) {
							// 如果是刪除 UserEntity 資料
							// 寄發通知信給該會員
							Emailer.SendMail(
								"service@Sample.com",
								user.Email,
								"帳號刪除通知",
								string.Format(
									"{0} {1} 您好,您的帳號已經於 {2} 成功刪除 ...",
									user.FullName,
									user.Gender == Gender.Male ? "先生" : "小姐",
									DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss")
								)
							);
						}
					}
				}
			});
		}

		public void DoBuiltinStart(object sender, EventArgs e) {}
		public void DoPluginStart(object sender, EventArgs e) { }
		public void DoPreDatabaseStart(object sender, EventArgs e) { }
		public void DoDatabaseStart(object sender, EventArgs e) { }
		public void DoPostDatabaseStart(object sender, EventArgs e) { }
		public void DoPostStart(object sender, EventArgs e) { }
		public void DoPluginTerminate(object sender, EventArgs e) { }
		public void DoBuiltinTerminate(object sender, EventArgs e) { }
		public void DoPostTerminate(object sender, EventArgs e) { }
	}
}

========================================
鐵人賽分享列表:Kuick Application & ORM Framework
開放原始碼專案:kuick.codeplex.com
直接下載原始碼:Kuick
下載相關文件檔:C# Code Conventions and Design Guideline
相關教學影片區:Kuick on YouTube


上一篇
Kuick -- 資料庫 Transaction (二)
下一篇
Kuick -- 資料批次處理
系列文
Kuick Application & ORM Framework34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言