views:

598

answers:

1

I'm having some difficulty with my Entity Framework context that is proving very troublesome to debug. I added a feature to my application yesterday that gave one of my entities an additional collection of child entities (called Models) and after updating one of my expressions to Include() that collection when I query for the parent object, my query is failing with an InvalidCastException when another one of the collections which worked fine before is Include()'d.

Unable to cast object of type 'System.Byte[]' to type 'System.IConvertible'

var b = DbEntities.Products.Include("Images").Include("Models").Include("Colors").FirstOrDefault(p => p.ID == id);

I fiddled with the expression and removed different collections/changed the Include()'d children and discovered it is this exact combination of items that causes the aforementioned exception. If I remove any of those Includes() there is no exception, but with those three children there is one every time I try to pull a single Product that has one or more entity in the Colors collection. The exception is not thrown if I remove the FirstOrDefault(p => p.ID == id) or if the Colors collection is empty.

It would seem that the addition of the Models collection was the breaking point for my query, but I am really not sure why.

The exact source of the exception is Mysql.Data and the stacktrace reads:

at MySql.Data.MySqlClient.MySqlDataReader.GetInt32(Int32 i)
at lambda_method(ExecutionScope , 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.ReadElement()
at System.Data.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
at SantekCMS.Data.ProductsRepository.GetProduct(Int32 id) in ProductsRepository.cs:line 65
at SantekCMS.Web.Controllers.Areas.Admin.ProductsController.EditProduct(Int32 id) in ProductsController.cs:line 111
at lambda_method(ExecutionScope , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
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__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

Entity Definitions (relevant fields only)

Product

  • int ID
  • EntityCollection<ProductColorOption> Colors
  • EntityCollection<ProductImage> Images
  • EntityCollection<ProductModel> Models

ProductColor

  • int ID

ProductColorOption

  • int ID
  • int ProductID
  • int ProductColorID

ProductModel

  • int ID
  • int ProductID

ProductImage

  • int ID
  • int ProductID
  • sbyte? Order

Relationships

  • Product.ID FK ProductImage.ProductID (One to Many)
  • Product.ID FK ProductColorOption.ProductID (One to Many)
  • Product.ID FK ProductModel.ProductID (One to Many)
  • ProductColor.ID FK ProductColorOption.ProductColorID (One to Many)

Thanks all!


Update

gaustin's suggestion below fixes problem (no more exception), but doesn't really target the actual issue. For that reason I'm going to leave the question 'unanswered'.

Update 2

I realize now that the bug pertains not to Entity Framework, but rather to the MySQL Data Provider. For some reason it is treating ProductColor.ID as a byte[] and then trying to cast it blindly to an int. This is not an Entity Framework problem at all. Curse you Sun Microsystems.

+2  A: 

Have you tried lazy loading the includes?

var product = DbEntities.Products.FirstOrDefault(p => p.Id == id);
product.Images.Load();

// ... and so on

That might be informative.

This also looks to be a known issue. I'm not sure if there's a known resolution at the moment. If there is I can't find it.

gaustin
I hadn't seen that post, interesting. I'll give lazy loading a shot.
Nathan Taylor
Thank you for bringing my attention the Load() method by the way. Did not know that was there! If I use Load() it seems to return the correct result without error. Doesn't answer my question per se but it does solve my problem!
Nathan Taylor
Well, that's something anyway. The Entity Framework can be really flaky, depending on what sort of things you're trying to do with it and with what provider. Hope they resolve a lot of this sort of thing in the next version.
gaustin
thanks for saving my day !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
effkay