Entity Framework - Sélectionnez des colonnes spécifiques et renvoyez des caractères fortement typés sans perdre la distribution.

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

Question

J'essaie de faire quelque chose de similaire à cet article pour lequel je ne retire pas toutes les colonnes d'une entité particulière. Cependant, mon cadre utilise l'héritage et je perds la portée du type d'entité après l'avoir converti en un type anonyme.

La structure de mon Entity Framework a une entité de base appelée Action . À partir de là, j'ai créé deux entités héritées, appelées événement et activité . Je souhaite extraire les dernières actions X et les transmettre à ma vue fortement typée, qui accepte une action et détermine à partir de là s'il s'agit d'une activité ou d'un événement et restitue la vue partielle correcte.

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

Je peux tirer les 10 derniers en tant que type anonyme et ensuite lancer:

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

Cependant, une fois que je transmets la nouvelle liste d'actions à ma vue fortement typée, elle perd toute possibilité de savoir s'il s'agit d'une activité ou d'un événement puisqu'elle a été convertie en action. Ma question est la suivante: sans exposer la colonne discriminante, existe-t-il un moyen de transformer chaque élément en un type approprié ou suis-je dans le mauvais sens?

Réponse acceptée

Un peu kludgy, mais fonctionnera:

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

Exemple avec des colonnes spécifiques à un type, en supposant qu'e.EventSpecific soit d'un type nullable.

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

Si o.EventSpecific est d'un type non nullable, vous devez le convertir en un type nullable dans la requête L2E.


Réponse populaire

Vous êtes probablement sur le mauvais chemin. Au début, je supposerais Action devrait être une classe abstraite et que vous ne devriez pas du tout pouvoir en créer des instances. Si vous ne récupérez alors qu'un sous-ensemble de propriétés et que ce sous-ensemble ne permet plus de discriminer les événements et les activités, il est probablement mal choisi d'essayer de les transformer en événements et activités.

Cela ne semble donc pas être un problème technique - il devrait être assez facile d'inclure certaines informations de discrimination dans le type anonyme - mais un problème de conception. Je suggère de repenser s'il est nécessaire de discriminer le résultat de la requête et si c'est vraiment une bonne idée de discriminer le résultat en l'absence d'un discriminateur.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow