1

I have looked at several possible solutions to my issue but did not find the right one.

I need a full set, that is, I need to fetch the types that are also of a base type. i.e. the ActionHistory type, as well as all others, which inherit from the ActionHistory base class. My problem was that I was getting all entities but those of the ActionUpdate type did not have the ActionUpdateDetails collection filled.

My problem is that I am unable to retrieve the ActionUpdateDetails data within the derived ActionUpdate class.

There are three classes in the model:

public class ActionHistory
{
public int Id {get;set;}
}

public class ActionUpdate : ActionHistory
{
public ICollection<ActionUpdateDetail> ActionUpdateDetails{get;set;}
}

public class ActionUpdateDetail
{
int Id{get;set;}
public string Field{get;set;}
public string Value{get;set;}
}

I tried implementing the solution from this suggestion: Entity Framework: Inheritance and Include

Like this:

var result = from actionHistory in ActionHistories
select new {
actionHistory,
actionUpdateDetails = actionHistory is ActionUpdate ? 
(actionHistory as ActionUpdate).ActionUpdateDetails : null
};

All I get is the exception message:

Unable to create a constant value of type 'System.Collections.Generic.ICollection`1'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Then I tried to simulate the situation outside the EF and it worked. I am using a POCO model and have extracted the involved classes into a separate project, filled the structure sample with data, and tested it with a success, i.e. ActionUpdateDetails collection was filled with the data.

Any help on this will be appreciated!

N.

Community
  • 1
  • 1
bignermo
  • 91
  • 1
  • 2
  • 11

2 Answers2

1

With regards to your answer, actually, the correct way is to use OfType<T>:

var actionUpdateDetails = ctx.ActionHistories
                       .OfType<ActionUpdate>()
                       .Select(x => x.ActionUpdateDetails)
                       .ToList();

This causes a database-side filter (inner join), whereas your solution performs implicit casting on items that may not be of that type - in which case you could get a null reference exception.

RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • Actually I forgot to mention that I need a full set, that is, I need to fetch the types that are also of a base type. i.e. the ActionHistory type, as well as all others, which inherit from the ActionHistory base class. My problem was that I was getting all entities but those of the ActionUpdate type did not have the ActionUpdateDetails collection filled. The solution I came up with has one (maybe more) side effect, it does not cast back to ActionHistory because of the extended anon. type :( – bignermo Dec 21 '10 at 10:46
  • Ahh, i didn't notice that in your Q - your not using abstract classes. Makes life difficult, especially with eager loading (as you have found). Your probably doing the right thing then. – RPM1984 Dec 21 '10 at 10:51
  • Nope, no abstract class, any idea on how to do that the proper way? – bignermo Dec 21 '10 at 12:50
  • Nope. Without abstract class, the "base" can be created and therefore you lose a lot of the polymorphic tricks (item must always be one of the derived items, base cannot be instantiated, etc). If possible, you should move to abstract classes. There is nothing in `ActionHistory` class except an ID anyway - so why even have the base? – RPM1984 Dec 21 '10 at 20:59
0
var result = from actionHistory in ActionHistories
select new
{
    actionHistory,
    ActionUpdateDetails = (actionHistory as ActionUpdate).ActionUpdateDetails
};
bignermo
  • 91
  • 1
  • 2
  • 11