32

I am using a LINQ statement that selects from various tables information I need to fill some Post / Post Comment style records. I'm getting a funny exception saying that the object must implement IConvertible when I try to iterate the record set. The funny part about it is that it seems to only occur when the anonymous type I'm using to hold the data contains more than 2 generic collections.

//select friend timeline posts posts
var pquery = from friend in fquery
    join post in db.game_timeline on friend.id equals post.user_id
    //join user in db.users on post.friend_id equals user.id into userGroup
    //join game in db.games on post.game_id equals game.game_id into gameGroup
    select new
    {
        Friend = friend,
        Post = post,

        Game = from game in db.games
          where game.game_id == post.game_id
          select game,

        Recipient = from user in db.users
          where user.id == post.user_id
          select user,

        Comments = from comment in db.timeline_comments
          where comment.post_id == post.id
          join users in db.users on comment.user_id equals users.id
          select new { User = users, Comment = comment }
    };

(Note: I am using MYSQL Connector/Net so things like Take and FirstOrDefault and things like that are not supported within the LINQ statements themselves, I have opted to use those methods during iteration as it does not raise an exception there)

The problem is, when all 3 fields (Game, Recipient, and Comments) are present. I get the exception "Object must implement IConvertible". BUT if I remove ANY one of the 3 field assignments (doesn't matter which one), it works just fine. Anybody know what's going on here?

Thanks in advance!

Ryan.

SilverX
  • 1,509
  • 16
  • 18
  • I've tried multiple ways, but currently I'm using a foreach loop – SilverX May 05 '11 at 20:33
  • does pquery.ToList() throw an exception? – Aducci May 05 '11 at 20:35
  • Yes, and so does ToArray – SilverX May 05 '11 at 20:36
  • Can we see how are you using the results and where are you getting the exception? – Ernesto May 05 '11 at 20:46
  • I don't get a chance to use the results. It fails on the loop initializer (or on the line containing ToArray() or ToList()). So if I were to put var results = pquery.ToList(); that's where the exception would be raised. – SilverX May 05 '11 at 20:50
  • Being that LINQ uses delayed execution I can only assume that since the exception is raised when I try to access the result set that there's a problem with the query itself. But like I said, it works fine with 2 fields filled by a nested query but fails when there's 3. And it doesn't matter which ones I remove or which ones I keep. – SilverX May 05 '11 at 20:52
  • Have you tried this code in linqpad ? – Orhan Cinar May 05 '11 at 21:00
  • 7
    I would first try to run the same code against MsSQL and if it passes I would report it as a bug of MySQL connector because I found several related questions on the web describing the similar issue only when working with MySQL. For example this: http://stackoverflow.com/questions/5741048/converting-tolist-throws-exception-object-must-implement-iconvertible – Ladislav Mrnka May 05 '11 at 21:45
  • LINQ does use delayed execution, so it will not show errors until you try to actually do something with the results (i.e. ToList(), ToArray()). From the exception, it seems as if one of your types are not matching up in your query. Check your types in MySQL and make sure they all line up properly. I would guess one of the where == statements is goofing up. – sharpper May 05 '11 at 22:34
  • Did you try renaming the Game or Comment variable? It looks to me that the default class name of the entities would be the same so maybe that's you're problem - linq isn't sure what you're trying to achieve? And btw in my eyes if you're going to use some annonymous class often enough then why not hard type it? – hyp May 06 '11 at 13:51
  • 1
    All suggestions seem rigth, but what is really weird is the fact that removing ANY of the variables makes it work. I would start with Ladislavs suggestion of trying the code against MSSQL. – Ernesto May 06 '11 at 14:44
  • +1 Ladislav's comment - I assume the MySQL LINQ provider isn't as mature as Microsoft's. You should show it to the vendor and file a bug report with them, unless the vendor comes along here and posts an answer, less likely. – John K May 08 '11 at 04:58
  • first of all, thanks for the suggestions. @ hyp - the class names are fine, the entities are generated with lowercase type names. The problem is that right now the code changes frequently as I'm constantly trying new things so changing a hardcoded object all the time would be trivial. Also I've seen little to no performance gains either way so I try not to be biased, the issue appears with hardcoded objects also. Though I have come to understand it is in fact a known issue with the MySql ADO.NET Data Provider and an unknown status on potential fixes – SilverX May 08 '11 at 15:42
  • 1
    I have managed to work around the issue by making a database change that enables me to select "Recipient" as an object rather than an entity collection (the reason it was a collection before was because it had the possibility to be null and a bunch of the Linq extensions are not fully supported prior to query execution ex. 'FirstOrDefault()'). This allows me to select the other 2 collections with no exception being raised. Also allowed me to truncate everything into a single statement bringing query execution to ~200ms (on a remote database) XD! – SilverX May 08 '11 at 15:47

1 Answers1

1

This is a guess, but I think your anonymous type might be attempting to duck-type to an enum when you've got more than two queries. If that's happening, then you'll get this complaint about not implementing IConvertible, as enum implements IConvertible, and your anonymous type (now derrived from enum) does not implement the interface.

Joe
  • 800
  • 4
  • 15
  • It would seem strange that an entity containing normal properties and a set of collection properties would be considered an enum when it's semantics suggest that it's the furthest thing from one. Very strange indeed. I plus voted your answer because this could very well be exactly what's happening whether it makes sense to me or not lol. Should I find out any more I'll mark it as an answer. – SilverX May 12 '11 at 19:58
  • I agree; it would be very strange. I'm not very knowledgeable about how the semantics of an object are analyzed for dynamic typing in C#, but the values should be incremental (I think) as opposed to C/C++ where the programmer can choose the enum values. We're still in the territory of guesses here, but it doesn't necessarily need to be casting to enum -- it could be any class that implements IConvertible. – Joe May 12 '11 at 20:23