7

Edit: Updated problem description based on testing - 12 Sep 2011.

I have this query that throws a NotSupportedException ("Specified method is not supported.") whenever I call .ToList().

IQueryable<FileDefinition> query = db
    .FileDefinitions
    .Include(x => x.DefinitionChangeLogs)
    .Include(x => x.FieldDefinitions.Select(y => y.DefinitionChangeLogs)) // bad
    .Include(x => x.FieldDefinitions.Select(y => y.FieldValidationTables)) // bad
    .Where(x => x.IsActive);
List<FileDefinition> retval = query.ToList();

If I comment out either line that I have commented as "bad", then the query works. I have also tried including different nested entities in my object model with the same effect. Including any 2 will cause a crash. By nested, I mean a navigation property of a navigation property. I also tried using the .Include methods with a string path: same result.

My table structure looks like this:

Db model

Db model 2

This is using MySQL 5.1 (InnoDB tables obviously) as the database store with MySQL Connector/NET 6.3.4.

So my question is: Why doesn't this work?

Note: I can get it to work if I explicitly load the related entities like in this link. But I want to know why EF hates my data model.

ANSWER: MySQL Connector is apparently not capable of handling the 2nd nested entity include. It throws the NotSupportedException, not .NET EF. This same error was also present when I tried this using EF4.0, but my research at the time led me to believe it was self-tracking entities causing the issue. I tried upgrading to latest Connector, but it started causing an Out of Sync error. This is yet another reason for me to hate MySQL.

Kasey Speakman
  • 4,511
  • 2
  • 32
  • 41
  • What happens if *only* leave the `Include` there you have marked as "bad" and remove the other two Includes? Does it work then? – Slauma Sep 10 '11 at 11:05
  • @Slauma Yes, the 2nd line works by itself. I did more testing, and it seems to be the combination of 2nd and 3rd includes that causes the crash. They work by themselves, but not together. The FieldValidationTables collection is loaded from a view in the database, and I had to manually setup the relationship in the EF model. It has the fields FieldDefinitionId and TableName. FieldDefintion 1<->* FieldValidationTable – Kasey Speakman Sep 12 '11 at 17:55
  • I have no idea what this problem is. You probably need to add more details to your question in order to get an answer (basically to make the problem reproducable for other people in a simple example model). – Slauma Sep 12 '11 at 18:38
  • It does not appear to let me run two includes on 2nd level sub-entities. For instance, including FieldDefintions.ValidationDefintions and FieldDefinitions.FieldValidationTables doesn't work either. I have also tried with the string-based-path include methods with the same effect. – Kasey Speakman Sep 12 '11 at 20:05
  • I had a similar problem when looking to see if it's possible to migrate from sql server to mysql (because of cheaper cost to make it easier to scale), but entity framework and mysql do not seem to be friends... – trees_are_great Jul 08 '20 at 11:40

2 Answers2

3

Maybe a little late to the party but i found the following workaround fairly useful in a current project:

IQueryable<FileDefinition> query = db.FileDefinitions
    .Include(x => x.FieldDefinitions.Select(y => y.DefinitionChangeLogs.Select(z => z.FieldDefinition.FieldValidationTables)))

Where rather than using a second row of includes, use Select to get back to the original navigation property and another Select to go forwards to the property you need to include.

Elliott
  • 2,669
  • 2
  • 23
  • 33
  • Thanks for the work-around. I'm no longer involved in that project, but hopefully it will help others. I'm also avoiding ORMs of late. – Kasey Speakman Apr 15 '14 at 16:10
2

I have made a little console application to test your scenario and this test application works:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

namespace EFIncludeTest
{
    public class Parent
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<ChildLevel1> ChildLevel1s { get; set; }
    }

    public class ChildLevel1
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<ChildLevel2a> ChildLevel2as { get; set; }
        public ICollection<ChildLevel2b> ChildLevel2bs { get; set; }
    }

    public class ChildLevel2a
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class ChildLevel2b
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<Parent> Parents { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Create entities to test
            using (var ctx = new MyContext())
            {
                var parent = new Parent
                {
                    Name = "Parent",
                    ChildLevel1s = new List<ChildLevel1>
                    {
                        new ChildLevel1
                        {
                            Name = "FirstChildLevel1",
                            ChildLevel2as = new List<ChildLevel2a>
                            {
                                new ChildLevel2a { Name = "FirstChildLevel2a" },
                                new ChildLevel2a { Name = "SecondChildLevel2a" }
                            },
                            ChildLevel2bs = new List<ChildLevel2b>
                            {
                                new ChildLevel2b { Name = "FirstChildLevel2b" },
                                new ChildLevel2b { Name = "SecondChildLevel2b" }
                            }
                        },

                        new ChildLevel1
                        {
                            Name = "SecondChildLevel1",
                            ChildLevel2as = new List<ChildLevel2a>
                            {
                                new ChildLevel2a { Name = "ThirdChildLevel2a" },
                                new ChildLevel2a { Name = "ForthChildLevel2a" }
                            },
                            ChildLevel2bs = new List<ChildLevel2b>
                            {
                                new ChildLevel2b { Name = "ThirdChildLevel2b" },
                                new ChildLevel2b { Name = "ForthChildLevel2b" }
                            }
                        },
                    }
                };

                ctx.Parents.Add(parent);
                ctx.SaveChanges();
            }

            // Retrieve in new context
            using (var ctx = new MyContext())
            {
                var parents = ctx.Parents
                    .Include(p => p.ChildLevel1s.Select(c => c.ChildLevel2as))
                    .Include(p => p.ChildLevel1s.Select(c => c.ChildLevel2bs))
                    .Where(p => p.Name == "Parent")
                    .ToList();

                // No exception occurs
                // Check in debugger: all children are loaded

                Console.ReadLine();
            }
        }
    }
}

My understanding was that this basically represents your model and the query you are trying (taking also your comments to your question into account). But somewhere must be an important difference which is not visible in the code snippets in your question and which makes your model fail to work.

Edit

I have tested the working console application above with MS SQL provider (SQL Server 2008 R2 Express DB), not MySQL Connector. Apparently this was the "important difference".

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • A more thorough review of the stack trace makes it appear that it's the MySQL Connector software that is throwing the exception. In other words, MySQL Connector is pro-actively not allowing this include to happen, not EF4.1. – Kasey Speakman Sep 12 '11 at 21:43
  • @Kasey: Good that you found the source of the problem! It's not the first limitation of EF MySQL Connector I've seen here. – Slauma Sep 12 '11 at 22:07
  • Yes, I have run into so many limitations and bugs with MySQL. I wish I could go back in time and start this project over with MSSQL. – Kasey Speakman Sep 12 '11 at 23:44