EF4.1多个嵌套实体包含获取NotSupportedException?

编辑:根据测试更新了问题描述 – 2011年9月12日。

我有这个查询,每当我调用.ToList()时抛出NotSupportedException(“不支持指定的方法。”)。

IQueryable 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 retval = query.ToList(); 

如果我注释掉我评论为“坏”的任一行,那么查询就可以了。 我也尝试在我的对象模型中包含不同的嵌套实体,效果相同。 包括任何2将导致崩溃。 通过嵌套,我的意思是导航属性的导航属性。 我也尝试将.Include方法与字符串路径一起使用:结果相同。

我的表结构如下所示:

Db模型

Db模型2

这显然使用MySQL 5.1(显然是InnoDB表)作为MySQL Connector / NET 6.3.4的数据库存储。

所以我的问题是:为什么这不起作用?

注意:如果我明确加载此链接中的相关实体,我可以让它工作。 但我想知道为什么EF讨厌我的数据模型。

解答:MySQL Connector显然无法处理第二个嵌套实体包含。 它抛出NotSupportedException,而不是.NET EF。 当我使用EF4.0尝试这个时,同样的错误也出现了,但我当时的研究让我相信它是导致问题的自我跟踪实体。 我尝试升级到最新的Connector,但它开始导致Out of Sync错误 。 这是我讨厌MySQL的另一个原因 。

我做了一个小的控制台应用程序来测试你的场景,这个测试应用程序工作:

 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 ChildLevel1s { get; set; } } public class ChildLevel1 { public int Id { get; set; } public string Name { get; set; } public ICollection ChildLevel2as { get; set; } public ICollection 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 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 { new ChildLevel1 { Name = "FirstChildLevel1", ChildLevel2as = new List { new ChildLevel2a { Name = "FirstChildLevel2a" }, new ChildLevel2a { Name = "SecondChildLevel2a" } }, ChildLevel2bs = new List { new ChildLevel2b { Name = "FirstChildLevel2b" }, new ChildLevel2b { Name = "SecondChildLevel2b" } } }, new ChildLevel1 { Name = "SecondChildLevel1", ChildLevel2as = new List { new ChildLevel2a { Name = "ThirdChildLevel2a" }, new ChildLevel2a { Name = "ForthChildLevel2a" } }, ChildLevel2bs = new List { 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(); } } } } 

我的理解是,这基本上代表了您的模型和您正在尝试的查询(同时考虑您对您的问题的评论)。 但某处必须是一个重要的区别,这在你的问题的代码片段中是看不到的,这使得你的模型无法正常工作。

编辑

我已经使用MS SQL提供程序(SQL Server 2008 R2 Express DB)测试了上面的工作控制台应用程序,而不是MySQL Connector。 显然这是“重要的区别”。

也许有点晚了,但我发现以下解决方法在当前项目中非常有用:

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

在不使用第二行包含的情况下,使用“选择”返回原始导航属性,使用另一个“选择”转到需要包含的属性。