Select specified columns and return strongly typed without loosing cast using Entity Framework.

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

Question

I'm attempting to do something like to these words, where I don't pull back every column from a specific entity, but my framework uses inheritence, and I lose scope of the entity type after it has been cast to an anonymous type.

My Entity Framework's structure has a basic entity with the name Action. I then used this information to build the entities Event and Activity. I want to get the latest X Actions and feed them to my strongly typed view, which receives an Action, assesses if it is an Activity or an Event, and then displays the appropriate partial view based on that determination.

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

As an anonymous type, I may choose the last 10 and then cast:

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

However, since the new List of Actions has been cast as an Action, it loses its ability to distinguish between being an Activity or an Event as I send it to my strongly typed view. Is there a method to cast each item to the correct type without revealing the discriminator column, or am I going about this the incorrect way?

1
5
5/23/2017 12:11:21 PM

Accepted Answer

a little clumsy, yet effective:

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

Example with columns for each kind, assuming that the type e.EventSpecific is 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();

If o.EventSpecific is a non-nullable type, you must change it in the L2E query so that it is a nullable type.

5
10/30/2009 4:07:05 PM

Popular Answer

Your direction is probably incorrect. I'd first presume thatAction You shouldn't be able to make any instances of it since it should be an abstract class. Making events and activities out of them is probably a bad idea if you only get a subset of the characteristics at that point and the subset makes it impossible to distinguish between the two.

Therefore, it seems to be a design issue rather than a technological one as it should be simple to add some discriminating information to the anonymous type. I advise reconsidering whether discriminating the query result is necessary, and if so, if doing it without a discriminator is actually a smart idea.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow