實體框架 - 選擇特定列並返回強類型而不會丟失強制轉換

asp.net-mvc entity-framework inheritance linq linq-to-sql

我正在嘗試做類似於這篇文章的內容 ,我不會從特定實體中撤回所有列,但是我的框架使用了繼承,並且在將其轉換為匿名類型後,我失去了實體類型的範圍。

我的Entity Framework的結構有一個名為Action的基本實體。從這裡開始,我創建了兩個名為EventActivity的繼承實體。我想撤回最後的X個動作並將它們傳遞給我的強類型視圖,該視圖接受一個Action,並從那裡確定它是一個Activity還是Event並呈現正確的局部視圖。

if(Model.GetType() == typeof(Event))
{
  //render Event view
}
else if(Model.GetType() == typeof(Activity))
{
  //render Activity view
}

我可以將最後10個作為匿名類型拉出然後進行轉換:

var result = from a in new DataContext().Actions
             where a.UserId == someGuidValue
             select new { a.CreatedOn, a.Summary };

List<Action> list = result.AsEnumerable()
                          .Select(o => new Action {
                                           CreatedOn = o.CreatedOn, 
                                           Summary = o.Summary
                          }).ToList();

但是,一旦我將新的動作列表傳遞給我的強類型視圖,它就失去了它是一個活動還是一個事件的範圍,因為它被強制轉換為動作。我的問題是,在沒有暴露鑑別器列的情況下,有沒有辦法將每個項目轉換為正確的類型,或者我是以錯誤的方式進行此操作?

一般承認的答案

有點kludgy,但會工作:

var result = from a in new DataContext().Actions
             where a.UserId == someGuidValue
             let IsEvent = a as Event != null
             select new { a.CreatedOn, IsEvent, a.Summary };

List<Action> list = result.AsEnumerable()
                          .Select(o => o.IsEvent ?
                                           (Action) new Event {
                                               CreatedOn = o.CreatedOn, 
                                               Summary = o.Summary
                                           }
                                           : (Action) new Activity {
                                               CreatedOn = o.CreatedOn, 
                                               Summary = o.Summary
                                           }
                          }).ToList();

具有特定於類型的列的示例, 假設e.EventSpecific屬於可空類型。

var result = from a in new DataContext().Actions
             where a.UserId == someGuidValue
             let ev = a as Event
             let IsEvent = ev != null
             select new { a.CreatedOn, IsEvent, a.Summary, ev.EventSpecific };

List<Action> list = result.AsEnumerable()
                          .Select(o => o.IsEvent ?
                                           (Action) new Event {
                                               CreatedOn = o.CreatedOn, 
                                               Summary = o.Summary,
                                               EventSpecific = o.EventSpecific
                                           }
                                           : (Action) new Activity {
                                               CreatedOn = o.CreatedOn, 
                                               Summary = o.Summary,
                                               EventSpecific = o.EventSpecific // will be null, but using o.EventSpecific saves casting
                                           }
                          }).ToList();

如果o.EventSpecific屬於非可空類型,則必須在L2E查詢中將其轉換為可空類型。


熱門答案

你可能走錯了路。首先,我假設Action應該是一個抽像類,你根本不應該創建它的實例。如果您只獲取屬性的子集並且子集不再允許區分事件和活動,那麼嘗試從中調用事件和活動可能是錯誤的方法。

所以它實際上似乎不是一個技術問題 - 在匿名類型中包含一些歧視信息應該很容易 - 但這是一個設計問題。我建議重新考慮是否需要區分查詢結果,如果是,如果在沒有鑑別器的情況下區分結果真的是個好主意。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因