2012年4月19日 星期四

取得 Entity Framework 中 Entity 對應 Table 的原生 Column Name

上一篇「取得 Entity Framework 中 Entity 的主鍵成員名稱(KeyMember)」裡面我們用了兩種方式來取得 Entity 主鍵成員,那既然都可以取得 KeyMember 的名稱與資訊了,哪麼同樣在 Entity 裡的其他欄位也應該可以拿得到吧!

當然可以。

取得的方式在以下的文章之中也提供兩種方式,不過就如同文章標題所說的,我只要取得原本 Table 中的 Column Name,至於其他因為關連而產生的 Entity Property 就不用取出。


看看使用 Entity Framework 所產生的 edmx 來看 Entity,我們以「Order_Detail」這個 Entity 來做說明,

image

圖中的(基本)屬性部分,如:OrderID, ProductID, UnitProce, Quantity, Discount,這些都是原本資料庫 Table 中既有的欄位,而「導覽屬性」,這是因為關連「Order」「Product」這兩張 Table 而產生的屬性,這是 EF 所產生的,並非 Table 原生的,如果我們要取得原生欄位所對應的屬性名稱,可以使用以下的方式,

public IEnumerable<PropertyInfo> GetEntityPropertyInfos(EntityObject entityObject)
{
    return entityObject.GetType()
        .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
        .Where(p => !p.PropertyType.IsClass);
}

藉由 EntityObject 來取得符合條件的 PropertyInfo,取得 PropertyInfo 之後就可以再取出我們所要的名稱,

程式應用並執行的結果:

image

 

但是這樣的方式就必須要先執行一次的資料查詢動作,以實例化一個 EntityObject 物件,這樣的方式在於彈性使用上就不見得好用,如果是想要將這樣類似的方法給放到一個架構的底層中也似乎不太理想。

 

在「EntityTypeBase 屬性」中,除了我們上一篇有用到的「KeyMembers」外,還有一個「Members」屬性,「Members」屬性,可以取得指定型別的成員清單,例如說,我們做個簡單的操作,利用「EntityTypeBase.Members」屬性來取得成員名稱,

public IEnumerable<EdmMember> GetEntityProperties(EntityTypeBase entityType)
{
    return entityType.Members.Select(x=>x);
}
public IEnumerable<string> GetEntityPropertyNames(EntityTypeBase entityType)
{
    return GetEntityProperties(entityType).Select(x=>x.Name);
}

執行結果:

image

這個執行結果因為是單純的取出型別成員的名稱,並未做過濾的處理,所以還是會包含非原生的成員名稱,那要怎麼去判別哪個成員是原生?哪些成員又是非原生呢?

 

我們直接來觀察一下成員的內容吧……

image

 

哇!不看還好,一取出來就讓人看到眼花了,直接跳到關鍵的地方好了,

image

EdmMember 成員的屬性裡面有一個「TypeUsage」屬性,這個屬性當中的「BuiltInTypeKind」屬性,我們所要關注的就是以下:

 

MSDN - BuiltInTypeKind 列舉型別

http://msdn.microsoft.com/zh-tw/library/bb343228.aspx

「PrimitiveType - 表示 PrimitiveType 型別的列舉成員。」

 

MSDN - PrimitiveType 類別

http://msdn.microsoft.com/zh-tw/library/system.data.metadata.edm.primitivetype.aspx

描述 .NET Framework 基本型別、概念模型基本型別以及儲存提供者專屬的基本型別。

 

所以我們就知道應該怎麼處理了吧!

再增加以下兩個方法:

public IEnumerable<EdmMember> GetPrimitiveEdmMembers(EntityTypeBase entityType)
{
    var properties = GetEntityProperties(entityType);
    
    return properties
        .Where(x=>x.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
        .Select(x=>x);
}
public IEnumerable<string> GetPrimitiveEdmMemberNames(EntityTypeBase entityType)
{
    return GetPrimitiveEdmMembers(entityType).Select(x=>x.Name);
}

 

執行結果:

image

 

如此我們就可以由 EDM 所定義的 ObjectSet<T> 經過再處裡後而得到 Entity 對應 Table 的 Column Name,不必再去透過查詢並實例化一個 EntityObject 後才能得知這些訊息,而且上述的方法也相當適合放入架構的底層中使用,除了可以取得原生 Column Name 之外,在「TypeUsage」中還可以取得相當多的資訊,可以善加利用。

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。