2017-04-18 68 views
2

我想从数据库中获取具有子对象列表的对象列表。实体框架核心包含筛选器

下面是一个例子

public class User 
{ 
    public int Id { get; set; } 
    public ICollection<Child> Childs { get; set; } 
} 

public class Child 
{ 
    public int Id { get; set; } 
    public string UserId { get; set; } 
    public User User { get; set; } 
} 

这里的问题是,我不能找到一种方法把用户的名单,并在同一时间的条件筛选童车以及。

我想是这样的:

users = _context.Users.Where(e => e.Childs.Any(ec => ec.Id > 1)) 

但是用这个例子中,如果条件不满足,它不会带给用户回来,我希望所有的用户,即使他们没有童车或条件没有得到满足。

也发现这个项目:https://github.com/zzzprojects/EntityFramework-Plus但它看起来像它不支持EF Core为我想要做的。

有没有人有任何建议?

感谢

+0

过滤包括 - 不支持所有EF版本,包括Core。不断询问SO。 –

+0

@IvanStoev感谢您的评论,但这并不能回答我的问题。你知道有其他的选择吗? – legollas007

+1

只有一些明确的加载/导航属性修正相关技巧,类似于*您还可以过滤哪些相关实体加载到内存中。*来自[documentation](https://docs.microsoft.com/en-us/ef/core/querying/related-data)的示例。但它需要查询实现。 –

回答

4

免责声明:我的项目Entity Framework Plus

我们的图书馆不支持查询过滤器还用于.NET的核心,由于N + 1查询问题的所有者。

在我们的EF6引擎下,我们的图书馆只做了一个简单的投影。

类似的东西来此使用您的信息:

var users = _Context.Users.Select(x => new { 
       Users = x, 
       Childs = x.Childs.Any(ec => ec.Id > 1) 
      }) 
      .ToList() 
      .Select(x => x.Users) 
      .ToList(); 

然而,对于EF核心,相同的投影做一个数据库往返让孩子每用户(N + 1个查询)

你可以尝试下面的投影,看看你是否得到相同的错误。

我相信,直到EF核心团队修复它,从我的知识来说,没有办法(我知道)过滤子实体。

SELECT [x].[Id], [x].[ColumnInt] 
FROM [Lefts] AS [x] 
go 
exec sp_executesql N'SELECT CASE 
    WHEN EXISTS (
     SELECT 1 
     FROM [Rights] AS [ec1] 
     WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId])) 
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
END',N'@_outer_Id1 int',@_outer_Id1=1 
go 
exec sp_reset_connection 
go 
exec sp_executesql N'SELECT CASE 
    WHEN EXISTS (
     SELECT 1 
     FROM [Rights] AS [ec1] 
     WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId])) 
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
END',N'@_outer_Id1 int',@_outer_Id1=2 
go 
exec sp_reset_connection 
go 
exec sp_executesql N'SELECT CASE 
    WHEN EXISTS (
     SELECT 1 
     FROM [Rights] AS [ec1] 
     WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId])) 
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
END',N'@_outer_Id1 int',@_outer_Id1=3 
go 
exec sp_reset_connection 
go 
exec sp_executesql N'SELECT CASE 
    WHEN EXISTS (
     SELECT 1 
     FROM [Rights] AS [ec1] 
     WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId])) 
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
END',N'@_outer_Id1 int',@_outer_Id1=4 
go 
exec sp_reset_connection 
go 
exec sp_executesql N'SELECT CASE 
    WHEN EXISTS (
     SELECT 1 
     FROM [Rights] AS [ec1] 
     WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId])) 
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) 
END',N'@_outer_Id1 int',@_outer_Id1=5 
go 

ANSWER子问题:

在.NET 2.0核心的新版本确实这个问题得到解决吗?

不幸的是,实体框架仍然没有能够与2.x版

例如正确处理好演员,这是LINQ使用铸造方法不起作用:

var ids = ctx.MyTables 
    .Cast<IMyTable>() 
    .Cast<MyTable>() 
    .Where(x => x.SomeKey.Equals(keyId)) 
    .Select(x => x.MyFieldIntegerIWant) 
    .ToList(); 
+0

随着.NET核心2.0的新发布,​​这个问题是否得到解决? – legollas007

+1

看到我添加的评论,总之,不... 2.0仍然有相同的问题 –

+0

当/如果他们解决了这个问题,_ **请** _返回并更新这个答案! –