• 沒有找到結果。

第三章   可調性軟體框架之設計

3.1  Model

3.1.3  動態技術

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

28

程式碼3.8 Tenant-Entity 屬性轉型之模擬 POCO

3.1.3 動態技術

在前兩個小節中提出MTA 實體設計模型及轉型解決方案,並經實驗證實符合在多租戶

中應用於Entity 對映實體資料表的需求,但這些僅是假設執行時期動態產生的模擬程 式碼,是對可調性對映技術的可行性評估。若要套用到多租戶軟體框架,這些程式碼 不可能如前兩節那樣是設計階段撰寫出來的程式碼,而是需要在執行時期依不同的租 戶提供不同的Tenant-Entity,故需要執行時期動態產生 Class 的技術方案。本小節將依 序列出下列三點解決方案。

1. 執行時期產生 Tenant-Entity

2. 執行時期實做 Tenant-Entity Object 3. 設計階段 Tenant-Entity 變數型態 3.1.3.1 執行時期產生Tenant-Entity

在.NET Framework 中可以使用 Emit 來達成執行時期產生程式碼,事實上要透過 Emit 建立的並不只有Tenant-Entity,在 Entity Framework 的運作中還需要提供 DbContext 來 管理Entity 及提供資料庫連線。因此 Emit 的過程需先建立 DbContext,再建立 Tenant-Entity,並在 Tenant DbContext 上宣告取用 Tenant-Entity 的 Property。DbContext 為了要 應付可以提供不同租戶連線不同資料庫的能力,本研究Emit 出來的 Tenant-DbContext 不直接繼承Entity Framework 提供的 DbContext,而是由可調性多租戶軟體框架提供具 有可提供連線參數的建構元的MtaDbContext,Emit 出來的 Tenant-Context 再繼承 MtaDbContext,這樣可以減少 Emit 時候的複雜性。

程式碼3.9 變更連線字串之 DbContext

框架為租戶產生 Tenant-Entity 之前須先到 Entity 資料表及 Field 資料表中取得要建 立Entity 的 metadata。有了這些資料再掌握動態時期產生 Class 的技術並配合前面兩小 節的模擬程式碼作為設計藍圖,便可在執行時期產生租戶需要的Tenant-Entity。但並非 所有Tenant-Entity 都是如模擬程式一般的繼承 Domain-Entity,在多租戶軟體框架中,

可能會提供一些完全租戶自訂的Tenant-Entity,這些 Tenant-Entity 雖然沒有 Domain Tenant 存在,但仍須直接繼承 MtaEntity。

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

30

程式碼3.10 Tenant-Entity 繼承之程式片段

有了TypeBuilder 之後,接著就可以經由 ILGnterator 來寫 IL,產生 Tenant-Entity 的Property。在建立好 Tenant-Entity 的 TypeBuilder 與 Property 後,便可在執行時期產 生租戶獨有的Tenant-Entity。

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

31

程式碼3.11 產生單純 Get/Set 的 Property 範例

程式碼3.12 Visual Studio 中使用中斷點觀察 TypeBuilder 的資訊

3.1.3.2 實做Class

在前一小段提到使用Emit 在執行時期產生 DbContext 與 Entity,但產生的 Class 是無法 直接使用,我們需要將Class 實做成 Object,在.NET Framework 中可以使用 Reflection 來可以達成。

在完成DbContext 與 Entity 的產生與實作之後,還需要解決一個非常重要的問題

DbContext 與 Entity 的型別都是執行時期才出現,開發時期還沒有這個型態的存在,直 接宣告為執行時期才會出現的型態,勢必無法通過編譯器的檢查。var 這是許多應用 Reflection 最常搭配的變數型態,但 var 實際上是編譯時期由編譯器決定型態,所以它 僅是語法糖衣,在這邊編譯器會將var 改為 Object,所以這邊直接寫 Object 是一樣的 結果,但變數型態宣告為Object 表示只能使用 Object 的屬性及方法,雖然可以使用 Reflection 提供的 GetProperty 與 GetMethod,但使用上會相當不方便。尤其 Tenant-Entity 將會被傳遞到 Controller 與 View,這會造成整個應用程式開發的不方便性,因此 使用應該使用Dynamic Binding 的技術,只要將型態宣告為 Dynamic,變數使用屬性及 方法時,編譯器就會跳過檢查,變數的真實型態會等到執行時期才確定,在那時候變 數的型態才會綁定為傳入物件的型態,這就是Dynamic Binding 或稱延遲綁定,將變數 綁定的時間由編譯時期延後到執行時期。 異甚大的部分,例如實作物件時要如【程式碼3.13】一樣使用 Reflection,取的 Tenant-Entity 資料時後,如果是 Universal Table Layout 就要如【程式碼 3.4】一樣,加上 TenantId 與 EntityId 的過濾條件,這些會讓開發者須要多學習不少技術及 MTA 的觀

相關文件