由 Dapper 傳回 dynamic 物件取得欄位清單

不用預先宣告強型別,查詢資料表後直接傳回 dynamic 是 Dapper 的強項,例如:var list = cn.Query("SELECT Col1,Col2 FROM T).ToList(); 將傳回 List<dynamic>,用 list.Fisrt().Col1 就能讀取欄位內容,簡潔又方便。

最近有個花式應用,想用通用函式接收 Dapper 查詢結果,自動列舉其中包含屬性(資料庫欄位)。一開始依循 System.Refelction 思維,想說用 GetType().GetProperties() 就可以搞定,不料踢到鐵板,Dapper 傳回的 dynamic 物件 .GetType() 結果為 null:

進一步追查,Dapper 傳回的 dynamic 骨子裡其實是個 DapperRow 型別,特別的是它實做了 IDictionary<string, object> 介面:

還記得既然要動態就動個痛快 - ExpandoObject介紹過 IDictionary<string, object> 的妙用,既然 DapperRow 是個 IDictionary<string, object> 一切好辦,轉型後用 .Keys 取回屬性清單,接下來就簡單了。

        static void Main(string[] args)
        {
            string sql = @"
SELECT 1 AS ColNum, SYSDATE AS ColDate, 'HELLO' AS ColString FROM DUAL UNION
SELECT 2 AS ColNum, SYSDATE AS ColDate, 'WORLD' AS ColString FROM DUAL
";
            using (var cn = new OracleConnection(cs))
            {
                var res = cn.Query(sql);
                StringBuilder sb = null;
                foreach (dynamic rec in res)
                {
                    var d = rec as IDictionary<string, object>;
                    if (sb == null)
                    {
                        sb = new StringBuilder(string.Join("\t", d.Keys.ToArray()));
                        sb.AppendLine();
                    }
                    sb.AppendLine(string.Join("\t",
                        d.Keys.Select(n => 
                            d[n] == null ? string.Empty : d[n].ToString()).ToArray()));
                }
                Console.WriteLine(sb.ToString());
 
                Console.Read();
            }
        }
        
 

經實測可成功列舉欄位名稱及內容:

COLNUM  COLDATE COLSTRING
1       2017/3/22 下午 09:07:30 HELLO
2       2017/3/22 下午 09:07:30 WORLD

最後,回到 DapperRow.GetType() 傳回 null 的謎團上,照理來說,GetType() 源自 Object 物件,查過 DapperRow 的原始碼並沒有覆寫 GetType(),想不出傳回 null 的理由。於是把問題丟上 stackoverflow,很快就有高手出面解惑,原來 DapperRow 實做了 DynamicMetaObject,攔截所有 dynamic 形式的成員存取,只要遇到非欄位名稱就傳回 null,因此不只 GetType(),呼叫 AsEnumerable() 也會傳回 null,所有謎團都解開了,結案!

歡迎推文分享:
Published 24 March 2017 08:14 AM 由 Jeffrey
Filed under:
Views: 4,420



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<March 2017>
SunMonTueWedThuFriSat
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication