iT邦幫忙

DAY 10
1

Kuick Application & ORM Framework系列 第 10

Kuick -- Schema Cache 規格快取

接下來三篇分享內容說明『規格快取』、『規格同步』、『資料初始化』。
下圖是啟動 Kuick 生命週期的 7 項事件中有關資料的部份,首先從『Schema Cache 規格快取』說起。

ORM 都應實作規格快取。

Kuick ORM 在 Kuick Application Lifecycle 資料庫啟動前 (PreDatabaseStart) 事件裡,完成規格快取,程式實作於 Kuick.Data.DataStart 類別的 DoPreDatabaseStart 方法。

foreach(Assembly assembly in Reflector.Assemblies) {
	List<Type> types = Reflector.GatherByAttribute<EntitySpec>(assembly);
	foreach(Type type in types) {
		if(type.IsAbstract) { continue; }
		IEntity one = Reflector.CreateInstance(type) as IEntity;
		if(null == one) { continue; }
		Table table = one.Table;
		if(null == table.Spec) { continue; }
		List<Column> columns = one.Columns;
		EntityCache.Add(one);
		il.Add("Entity Name", one.EntityName);
	}
}

這段程式,從所有組件裡取出有在 class 定義 EntitySpec Attribute 的類別,產生實體並經由呼叫 Table 與 Columns 屬性,取得完整的資料規格後,再將其快取於 EntityCache 類別。

更細節的快取內容請查看 Kuick.Data.Entity 的 Table 與 Columns 屬性

<Entity Table property>
將資料表的『CategoryAttribute 分類』、『DescriptionAttribute 描述』、『EntitySpec 規格』、『EntityMapping 多對多參照』、『EntityIndex 索引』、『EntityVisual 分頁顯示設定』一併快取。

public Table Table
{
	get
	{
		if(null == _Table) {
			lock(_Lock) {
				if(null == _Table) {
					if(Heartbeat.Singleton.PreDatabaseStartFinished) {
						IEntity instance = EntityCache.Get(EntityName);
						if(null == instance) { throw new NullReferenceException(); }
						_Table = instance.Table;
					} else {
						_Table = new Table();
						object[] objs = this.GetType().GetCustomAttributes(true);
						CategoryAttribute category = null;
						DescriptionAttribute description = null;
						EntitySpec spec = null;
						List<EntityMapping> mappings = new List<EntityMapping>();
						List<EntityIndex> indexes = new List<EntityIndex>();
						EntityVisual visual = null;
						foreach(object x in objs) {
							if(x is CategoryAttribute) {
								category = (CategoryAttribute)x;
								continue;
							}
							if(x is DescriptionAttribute) {
								description = (DescriptionAttribute)x;
								continue;
							}
							if(x is EntitySpec) {
								spec = (EntitySpec)x;
								spec.Table = _Table;
								continue;
							}
							if(x is EntityIndex) {
								EntityIndex index = (EntityIndex)x;
								index.Table = _Table;
								indexes.Add(index);
								continue;
							}
							if(x is EntityMapping) {
								EntityMapping mapping = (EntityMapping)x;
								mapping.Table = _Table;
								mappings.Add(mapping);
								continue;
							}
							if(x is EntityVisual) {
								visual = (EntityVisual)x;
								visual.Table = _Table;
								continue;
							}
						}

						// CategoryAttribute
						if(null == category) {
							category = new CategoryAttribute(
								this.GetType().Namespace
							);
						}

						// DescriptionAttribute
						if(null == description) {
							description = new DescriptionAttribute(
								this.GetType().Name.TrimEnd(Constants.Entity.Suffix)
							);
						}

						_Table.EntityName = EntityName;
						_Table.TableName = TableName;
						_Table.Class = this.GetType();

						_Table.Category = category;
						_Table.Description = description;
						_Table.Spec = spec;
						_Table.Indexes = indexes;
						_Table.Mappings = mappings;
						_Table.Visual = visual;
					}
				}
			}
		}
		return _Table;
	}
}

<Entity Columns property>
將資料欄位的『CategoryAttribute 分類』、『DescriptionAttribute 描述』、『ColumnSpec 規格』、『ColumnEncrypt 加解密』、『ColumnRefer 參照』、『ColumnInitiate 初始值』、『ColumnVisual 顯示設定』、『IValidation 資料檢驗條件』一併快取。

public List<Column> Columns
{
	get
	{
		if(null == _Columns) {
			lock(_Lock) {
				if(null == _Columns) {
					if(Heartbeat.Singleton.PreDatabaseStartFinished) {
						IEntity instance = EntityCache.Get(EntityName);
						if(null == instance) { throw new NullReferenceException(); }
						_Columns = instance.Columns;
					} else {
						_Columns = new List<Column>();
						foreach(PropertyInfo info in this.GetType().GetProperties()) {
							Column column = new Column();
							object[] objs = info.GetCustomAttributes(true);
							CategoryAttribute category = null;
							DescriptionAttribute description = null;
							ColumnSpec spec = null;
							ColumnEncrypt encryptor = null;
							ColumnRefer refer = null;
							ColumnInitiate initiate = null;
							ColumnVisual visual = null;
							List<IValidation> validations = new List<IValidation>();
							foreach(object x in objs) {
								if(x is CategoryAttribute) {
									category = (CategoryAttribute)x;
									continue;
								}
								if(x is DescriptionAttribute) {
									description = (DescriptionAttribute)x;
									continue;
								}
								if(x is ColumnSpec) {
									spec = (ColumnSpec)x;
									spec.Column = column;
									continue;
								}
								if(x is ColumnEncrypt) {
									encryptor = (ColumnEncrypt)x;
									encryptor.Column = column;
									continue;
								}
								if(x is ColumnRefer) {
									refer = (ColumnRefer)x;
									refer.Column = column;
									if(refer.Style == ReferValue.Self) {
										refer.Type = this.GetType();
									}
									continue;
								}
								if(x is ColumnInitiate) {
									initiate = (ColumnInitiate)x;
									initiate.Column = column;
									continue;
								}
								if(x is ColumnVisual) {
									visual = (ColumnVisual)x;
									visual.Column = column;
									continue;
								}
								if(x is IValidation) {
									IValidation validation = (IValidation)x;
									Reflector.SetValue(validation, "Column", column);
									validations.Add(validation);
									continue;
								}
							}

							// ColumnSpec
							if(null == spec) {
								continue;
							} else {
								if(Checker.IsNull(spec.ColumnName)) {
									spec.ColumnName = SqlNamingConvention
										.ToColumnName(this.GetType(), info);
								}
							}

							// CategoryAttribute
							if(null == category) {
								category = new CategoryAttribute(
									Constants.Default.Category
								);
							}

							// DescriptionAttribute
							if(null == description) {
								description = new DescriptionAttribute(
									Formator.DividePascalCasing(info.PropertyType.Name)
								);
							}

							// ColumnRefer
							if(null == refer) {
								refer = new ColumnRefer(ReferValue.None);
							}

							// ColumnInitiate
							if(null == initiate) {
								initiate = new ColumnInitiate(InitiateValue.None);
							}

							// ColumnVisual
							if(null == visual) {
								visual = new ColumnVisual();
							}

							column.TableName = TableName;
							column.EntityName = EntityName;
							column.Category = category;
							column.Description = description;
							column.Property = info;
							column.Spec = spec;
							column.Refer = refer;
							column.Initiate = initiate;
							column.Visual = visual;
							column.Encryption = encryptor;
							column.Validations = validations;
							column.Foolproof();

							if(
								Current.Data.Concurrency
								||
								column.Spec.ColumnName != VERSION_NUMBER) {
								_Columns.Add(column);
							}
						}
					}
				}
			}
		}
		return _Columns;
	}
}

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


上一篇
Kuick -- Entity Column 定義
下一篇
Kuick -- Schema Sync 規格同步
系列文
Kuick Application & ORM Framework34

1 則留言

0
abcg5
iT邦新手 5 級 ‧ 2012-10-23 23:59:32

請問一下,我想將kuick中對db Schema 處理的部分,應用到SQL SSIS 2005中
,從下載來的檔案並沒有提到的那些dll檔,有source code,是指自行編譯為dll檔嗎?

這方面有點陌生,故此詢問一下,編譯出來的檔案有x86 或 x64的系統限制嗎?

另外如何這不適合發問,在煩請砍文,謝謝!

kevinjong iT邦新手 3 級 ‧ 2012-10-28 09:26:38 檢舉

迎歡 abcg5 的發問,如果只需要 dll,可以參考『Kuick -- 使用 NuGet 建立 ORM 專案』這篇分享說明,或是下載原始檔進行編譯,目前的專案編譯設定皆為 Any CPU,這也可以自行調整後再編譯。
近日會有更新一版,會額外將 dll 單獨提供下載。
您也可以直接發 email 給我 kevinjong@gmail.com

我要留言

立即登入留言