昨天研究EF View Primary Key錯置問題時留下一個謎--當View Primary Key不正確時,出現離譜的查詢結果:

T001 FBI - Fox
T001 FBI - Fox
T002 Bloggers - Jeffrey
T002 Bloggers - Jeffrey
T002 Bloggers - Jeffrey
T002 Bloggers - Jeffrey
T003 Avengers - Captain America
T003 Avengers - Captain America
T003 Avengers - Captain America
T003 Avengers - Captain America

每個團隊的成員筆數正確,但是成員姓名全部相同,都被換成該Team第一位成員的姓名。經過一番研究與查詢,在Stack Overflow網站(它是啥?)找到一則很棒的討論。有人提問類似問題,網友Marc Gravel提供了很經典的答案: (可惜網站每則回答只能按一次讚,不然我想按10次)

It looks to me like you have a borked primary key. The "identity management" aspect of LINQ-to-SQL and EF means that it is obliged to give you back the same instance whenever it sees the same primary key value(s) for the same object type.

一語驚醒夢中人!!

EF很認真地看待Primary Key,當兩筆資料的Primary Key相同,對EF而言就是同一筆資料,所以不會費神再去搞出另一個Primary Key相同但部分欄位相異的資料物件(註: 在關聯式資料庫裡,一個資料表不該並存兩筆PK相同的資料,若是真的出現那就是天理不容,國本動搖,DBA該被抓去坐牢),而會將兩筆資料視為同一物件個體。

這個原則可以解釋為什麼我們的查詢中出現了2位Fox、4隻Jeffrey跟4個美國隊長。結論是,當我們的資料背離了Model的根本PK原則,得到詭異結果也是天經地義~~

底下用一個案例來實證推論。我們先建立一個BadPKData資料表,有兩個欄位PK及Name,指定欄位PK為Primary Key:

將BadPKData加入edmx中,VS2010很聰慧地認出PK是Primary Key,順利建好Model。

接著惡搞時間來了,我們故意把Primary Key限制拿掉,再塞入兩筆PK都是'1'的矛盾資料,刻意製造出不合常理的PK重複情境。

使用foreach (var t in ctx.BadPKData)列出剛才塞入的兩筆資料,果然,兩筆的Name都是"Jeffrey",驗證了EF以Primary Key識別資料差異性的論點成立。

結論是,在程式查詢結果中看到離奇的重複資料時,請先檢查Entity Framework Model的Primary Key是否設定正確。又上了一課!


Comments

Be the first to post a comment

Post a comment