在 Silverlight + WCF RIA Services + ADO.NET Entity Framework 架構中,遇到一個極具迷惑性的問題:資料庫視圖查詢結果正確,但實體模型查詢結果卻少筆資料,且重複鍵值的列被合併。根因在於 Entity Framework 依賴 Entity Key 唯一性構建結果集。
問題重現場景
- 資料庫建立視圖
vw_DesksAndUsers 關聯 Desk、User 表,T-SQL 查詢返回預期多筆資料(含相同 DeskId 不同 User 的列)
- VS2010 新增 ADO.NET 實體資料模型 (.edmx),勾選該視圖
- EF 自動推斷 Entity Key:
DeskId、IsPlaying(來自 Desk 表)
- 建立 Domain Service,Silverlight DataGrid 繫結該視圖
- 運行發現:DataGrid 僅顯示每個 DeskId 一筆資料,其他 User 列消失
根因分析
EF 將實體模型視為「物件圖」,Entity Key 必須唯一識別一個實體實例。視圖中 DeskId 重複(一張桌子多用戶),但 EF 依自動推斷的 Key (DeskId, IsPlaying) 去重,導致同 DeskId 不同 User 的列被視為同一實體而捨棄。
解決方案:修正 .edmx 中的 Entity Key
- 開啟 .edmx 設計介面,右鍵視圖實體 → Properties
- 在 Entity Key 區域,勾選真正能唯一識別每列的欄位組合(如
DeskId + UserId)
- 取消勾選非唯一欄位(如
IsPlaying)
- 重新建置專案,重新生成 Domain Service

驗證結果
修正後重新運行,Silverlight DataGrid 完整顯示所有資料列,與 T-SQL 直接查詢結果一致。

深層啟示
- EF/LINQ 生成的 T-SQL 與手寫 SQL 可能不同,Entity Key 語義影響物質化過程
- 視圖/無主鍵表導入 EF 時,務必手動檢查並修正 Entity Key
- Silverlight Domain Service 直接反映 EF 物質化結果,上層無法修正
- 此問題不限於 Silverlight,任何 EF 消費端(MVC、Web API、WPF)均會受影響
最佳實踐
- 資料庫視圖設計時,盡量包含唯一識別欄位組合
- .edmx 更新自資料庫後,檢查新增實體的 Key 設定
- 無法確保唯一性時,考慮在視圖加入
ROW_NUMBER() OVER(...) 產生代理鍵
- 單元測試驗證 EF 查詢筆數與原生 SQL 一致