結論
Dapper splitOn 無論是用 "column1" 或 "column1,column2,..." 等方式,一定要符合下列條件,否則怎麼走怎麼採坑。- column1, column2, ... 一定要出現在 select 出來的結果欄位名稱中。沒做到就會出現執行階段錯誤:
- System.ArgumentException: When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id 參數名稱: splitOn
- column1, column2, ... 有對應的 Object Fields 或 Properties 中,其值為 NULL,產生 null。若非 NULL,會產生實體。
- column1, column2, ... 若沒在對應的 Object Fields 或 Properties 中,就算其值為 NULL。還是會產生全部 Field 或 Property 都是預設值的實體,而不是產生 null 。
緣由
一個專案,搞瘋一個程序猿。
由於此專案其使用的資料庫,官方提供的函式庫在 Entity Framework (Core) 有很多問題及限制。故只能使用 ADO.NET 技術,而且還有限制(...)。
問題1
一直有這類需求:
select
t1.*,
t2.*,
t3.*
from
table1 t1
left join
table2 t2
on
t1.table1_id = t2.table2_id
left join
table3 t3
on
t1.table1_id = t3.table3_id
...
嘗試1
於是先打了以下程式碼。
cn.Query<Table1,Table2,Table3,Table1>(
@"select
t1.*,
t2.*,
t3.*
from
table1 t1
left join
table2 t2
on
t1.table1_id = t2.table2_id
left join
table3 t3
on
t1.table1_id = t3.table3_id
",
(table1,table2,table3) =>
{
table1.Table2 = table2;
table1.Table3 = table3;
return table1;
},
splitOn: "table2_id,table3_id"
);
但在取得結果上一直不正確,Table2 有些與 Table1 及 Table3 相同名稱的欄位會取得預設值或 Table1 的值,但 Table3 卻取得 Table2 的欄位值。
解決1
原來是欄位順序的問題,table2_id 及 table3_id 不是第一個欄位。
WTF...
嘗試2
於是改了以下程式碼。
cn.Query<Table1,Table2,Table3,Table1>(
@"select
t1.*,
t2.table2_id,
t2.*,
t3.table3_id,
t3.*
from
table1 t1
left join
table2 t2
on
t1.table1_id = t2.table2_id
left join
table3 t3
on
t1.table1_id = t3.table3_id
",
(table1,table2,table3) =>
{
table1.Table2 = table2;
table1.Table3 = table3;
return table1;
},
splitOn: "table2_id,table3_id"
);
但會因為 table2_id 及 table3_id 出現了兩次,視 table2 及 table3 欄位重複程度或順序還是會出問題。
解決2
只能再想想既可無視兩者欄位名稱重複,又可切得漂亮的方法。
嘗試3
在每個 Entity (Table1, Table2, Table3) 增加一個文字欄位 SplitOn,怕麻煩可新增 Entity Base Class 其它 Entity 繼承他即可。
記得若是有使用 Entity Framework (Core) Mapping 需要排除 (Ignore) 此欄位。
下查詢。
cn.Query<Table1,Table2,Table3,Table1>(
@"select
t1.*,
t2.table2_id split_on,
t2.*,
t3.table3_id split_on,
t3.*
from
table1 t1
left join
table2 t2
on
t1.table1_id = t2.table2_id
left join
table3 t3
on
t1.table1_id = t3.table3_id
",
(table1,table2,table3) =>
{
table1.Table2 = table2;
table1.Table3 = table3;
return table1;
},
splitOn: "split_on"
);
解決3
目前最漂亮的方法,但有點麻煩需要處理 Entity 的欄位。
最主要是卡在 SplitOn 的欄位必須在 Entity 中出現,不然不會這麼麻煩。
留言
張貼留言
歡迎留言給我們