Entity Framework - Wählen Sie bestimmte Spalten aus und geben Sie stark typisiert zurück, ohne die Umwandlung zu verlieren

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

Frage

Ich versuche, etwas Ähnliches wie diesen Beitrag zu tun, bei dem ich nicht alle Spalten einer bestimmten Entität zurückziehe. Allerdings nutzt mein Framework die Vererbung und ich verliere den Umfang des Entitätstyps, nachdem er in einen anonymen Typ umgewandelt wurde.

Die Struktur meines Entity Frameworks hat eine Basisentität namens Action . Von hier aus habe ich zwei geerbte Entitäten namens Event und Activity erstellt . Ich möchte die letzten X-Aktionen zurückziehen und sie meiner stark typisierten Ansicht übergeben, die eine Aktion akzeptiert und von dort aus bestimmt, ob es sich um eine Aktivität oder ein Ereignis handelt und die korrekte Teilansicht wiedergibt.

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

Ich kann die letzten 10 als anonymen Typ ziehen und dann werfen:

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();

Sobald ich die neue Liste der Aktionen an meine stark typisierte Ansicht übergeben habe, verliert sie jedoch den Umfang, ob es sich um eine Aktivität oder ein Ereignis handelt, da sie als Aktion umgesetzt wurde. Meine Frage ist, ohne die Diskriminator-Spalte zu entlarven, gibt es eine Möglichkeit, jeden Gegenstand in den richtigen Typ umzuwandeln, oder gehe ich den falschen Weg?

Akzeptierte Antwort

Ein bisschen kludgy, aber funktioniert:

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();

Beispiel mit typspezifischen Spalten, unter der Annahme , dass es sich bei e.EventSpecific um einen nullwertfähigen Typ handelt.

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();

Wenn o.EventSpecific einen nicht-nullfähigen Typ hat, müssen Sie ihn in der nullwertfähigen Klasse in der L2E-Abfrage konvertieren.


Beliebte Antwort

Sie sind wahrscheinlich auf dem falschen Weg. Zuerst würde ich davon ausgehen, dass Action eine abstrakte Klasse sein sollte, und Sie sollten überhaupt keine Instanzen davon erstellen können. Wenn Sie dann nur eine Teilmenge der Eigenschaften abrufen und die Teilmenge nicht mehr zwischen Ereignissen und Aktivitäten unterscheiden kann, ist dies wahrscheinlich der falsche Weg, um Ereignisse und Aktivitäten aus ihnen zu machen.

Es scheint also kein technisches Problem zu sein - es sollte ziemlich einfach sein, einige Diskriminierungsinformationen in den anonymen Typ aufzunehmen -, aber ein Designproblem. Ich schlage vor, zu überdenken, ob es erforderlich ist, das Abfrageergebnis zu unterscheiden, und wenn ja, wenn es wirklich eine gute Idee ist, das Ergebnis zu unterscheiden, wenn kein Diskriminator vorhanden ist.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum