2

I have an Entity Framework model (some properties have been excluded to keep it simple):

public class Media { public int MediaID { get; set; } public ICollection<Track> Tracks { get; set; } public ICollection<RelatedMedia> RelatedMedias { get; set; } } 

I then have my DbContext:

public class MediaServiceContext : DbContext { public DbSet<Media> Medias { get; set; } } 

I can then retrieve data using the following, and it works great:

public Media Media_Get(int id) { using (MediaServiceContext mc = new MediaServiceContext()) { return mc.Medias.Include("Tracks").Include("RelatedMedias").Single(m => m.MediaID == id); } } 

My question is, I may not want to load one or both of the related entities in some cases, depending on which part of my application is calling this code; how can I make the Includes dynamic?

I have tried this:

public Media Media_Get(int id, bool includeRelated, bool includeTracks) { using (MediaServiceContext mc = new MediaServiceContext()) { IQueryable<Media> query = mc.Medias; if (includeRelated) query = query.Include("RelatedMedias"); if (includeTracks) query = query.Include("Tracks"); return query.Single(m => m.MediaID == id); } } 

...but I get a 'Specified cast in not valid' exception.

I have also tried this proposed solution, but it produces a 'unable to cast DbQuery to ObjectQuery' exception. Changing the extension method in the linked solution from '(ObjectQuery)source' to '(DbQuery)source' then causes the same 'Specified cast in not valid' exception.

I have hunted high and low for a solution on this but with no luck. Any help would be much appreciated.

Amendment - Here's the stack trace:

 at System.Data.SqlClient.SqlBuffer.get_Int64() at lambda_method(Closure , Shaper ) at System.Data.Common.Internal.Materialization.Coordinator.HasNextElement(Shaper shaper) at System.Data.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MoveNext() at System.Data.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.TryReadToNextElement() at System.Data.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source) at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) at API.Areas.V1.Models.RetailerManager.Media_Get(Int32 id, String retailerKey, Boolean includeLicenses, Boolean includeProperties, Boolean includeRelated, Boolean includeTracks) in C:\Users\garth\Documents\Development\WebApplications\api\Areas\V1\Models\RetailerManager.cs:line 28 at API.Areas.V1.Controllers.RetailerController.Media(Nullable`1 id, String httpVerb, Boolean includeLicenses, Boolean includeProperties, Boolean includeRelated, Boolean includeTracks) in C:\Users\garth\Documents\Development\WebApplications\api\Areas\V1\Controllers\RetailerController.cs:line 25 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) 
6
  • 2
    Imo it should really work. Can you test to use the strongly typed version of Include: query = query.Include(m => m.RelatedMedias); and query = query.Include(m => m.Tracks);. It should make no difference at runtime but perhaps we see a bit more if it behaves different. Commented Dec 20, 2011 at 20:56
  • Yeah already tried that I'm afraid, produces the same result. Commented Dec 21, 2011 at 10:15
  • I've tested such an example and it worked for me. "Specified cast in not valid" seems to make no sense to me with your example code. Can you show the full exception message and the stacktrace? Commented Dec 21, 2011 at 10:50
  • I totally agree, that's why this has been driving me nuts. See stack trace amended above. Commented Dec 21, 2011 at 20:35
  • Your stack trace seems to be pointing at a long to int32 problem. Commented Dec 21, 2011 at 20:44

1 Answer 1

1

Your stack trace shows that .SingleOrDefault() caused this exception, but I don't see .SingleOrDefault() in your code.

I do see this:

return query.Single(m => m.MediaID == id); 

Is it possible that Media.MediaID is a long and not an int?

Update

As another alternative to answer your original question, I answered a question a couple of weeks ago in relation to this. The sample code in my answer has to do with dynamic order by, but we use a very similar pattern for dynamic eager loading (see the first comment after my answer).

Instead of a method signature like this:

public Media Media_Get(int id, bool includeRelated, bool includeTracks) 

Your signature would look more like this:

public Media Media_Get(MediaGetter mediaGetter) 

...and you would use it like this:

var media = someInstance.Media_Get( new MediaGetter { ID = id, } .EagerLoad(m => m.Tracks) .EagerLoad(m => m.RelatedTracks) ); 
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your response. My stack trace doesn't quite match as I had amended that later on during which time I was trying different things, ie... .Single as well as .SingleOrDefault. They both however produce the same result. With regards to the MediaID property, this is an Int. With regards to your proposed solution, I will take closer look at this when I'm back in the office after the xmas/new year break, however wouldn't the .EagerLoad method just be doing a .Include on the query object which would potentially produce the same result for me? Thanks again.
@gmeister_99, yes, you would have to fix this exception first. In the database, is MediaID stored as int or bigint? As keni mentioned, you have this at the top of the stack: System.Data.SqlClient.SqlBuffer.get_Int64() <-- this is 64 bit long, not 32 bit int.
Thanks again for your responses. I've broken the entity relationships down and found the offending property which was not actually on the Media object but on the related Track object. The property was indeed a long when it should have been an int. My original solution works fine now :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.