2014-03-05 123 views
3

我正在使用實體框架6設計多租戶應用程序。此應用程序中的一個關鍵要求是每個承租人都可以擁有自定義表格。這意味着一個具有相同名稱的表可能在模式之間有所不同。自定義數據庫表的自定義實體生成器

例如,一個承租人可能有一個「人」表,其中包括:ID,名字,姓氏,出生日期。

另一個房客可能有一個「人」表,其中包括:ID,名字,姓氏,出生日期,收藏顏色。

當我設計我的模型,這就是我:

public class Person 
{ 
    public int ID { get; set; } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public DateTime BirthDate { get; set; } 
} 

這適用於第一個租戶,但在第二承租人自定義列將不會加載。我所希望做的是這樣的:

public class Person : Dictionary<string, object> 
{ 
    public int ID { get; set; } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public DateTime BirthDate { get; set; } 
} 

,然後寫一個自定義的模型映射器/生成器,將會把誰沒有匹配的屬性到字典集合的表列。

有幾個問題是:

  1. 實體框架創建一個SELECT語句,列出了所有的 屬性/列在模型中。不知怎的,我需要用*替換 列表,以便所有列,即使是EF不知道 的列,都會返回。

  2. 我需要能夠攔截結果集,將已知列 映射到模型屬性,並將未知列置於 字典中。

這是否可能?有沒有更好的方法來解決這個問題?

+0

那麼,看看'EF'是否能夠提供一些開箱即用的東西是非常有趣的。我能想到的是製作像CustomColumns這樣的枚舉類型,並且有一個像PeopleCustomColumns結點表這樣的表,或者按照這個順序。 – Leron

+1

是的,這個問題有三種解決方案:1.有另一個緊密相關的表「extra」列信息2.向每個可以用於自定義用途的表添加通用列,以及3.在模式之間處理具有不同佈局的表。前兩個並不難創建,但需要額外的開銷。由於靈活性和缺乏管理費用,最後的解決方案對我來說是理想的。 – Sparafusile

回答

3

我遇到了類似的問題,一個更通用的問題。

在我的應用程序中,最終用戶能夠定義他的數據對象。在設計時我甚至不知道Person課程。這意味着從設計的角度來說,將屬性添加到我在運行時甚至不知道的類中。 :)

剛開始,忘了實體框架。你不會試圖解決這個問題。我花了一些時間比較和分析解決方案。好消息是:我找到了一個!

我現在正在做的是允許用戶指定數據對象的名稱以及屬性。接下來,我使用CodeDOM根據用戶數據生成一個包含POCO類的程序集。所有類都從一個空的IDataObject接口派生而來。

最後使用反射,我加載的類和再次使用它們根據用戶的需求。從空接口繼承是非常有用的主要有兩個原因:

  • 使用反射獲取類:我正在使用接口來獲取從它派生的類。 Type.GetType()有助於選擇我需要的。
  • 我正在使用的ORM(見下文)正在使用泛型方法。我只是在我的方法中添加一個where T : IDataObject來限制使用情況。

我正在使用的ORM是ServiceStack OrmLite。 V4不是免費的,但你仍然可以使用V3(你可以從NuGet獲得)。順便說一下,它是最快的.NET ORM之一。

OrmLite要求的所有對象是正在插入/更新的對象的類型等。爲此,我使用dynamic關鍵字來保持類型解析爲運行時。看看這裏:這裏

更多信息有關的CodeDOM:

順便說一句,我很抱歉,沒有張貼代碼示例和這是因爲兩個原因:規模和僱主知識產權。

最後,這是另一個問題,我試圖解決這個問題。這可能會有所幫助。

而且對不起,我忘了提,裝配一代爲每個最終用戶來完成。如果要擴展現有類型(因爲要生成新的程序集版本),這可能會導致應用程序重新啓動。 OrmLite負責使用其CreateTable<T>(true)方法擴展表格。