实体框架核心包含过滤器

时间:2017-04-18 08:21:57

标签: c# entity-framework entity-framework-core

我正在尝试从数据库中提供一个包含子对象列表的对象列表。

这是一个例子

 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; }
 }

这里的问题是我无法找到一种方法来提供用户列表并同时过滤具有条件的Childs。

我试过这样的事情:

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

但是如果不满足条件就使用这个例子它不会带回用户,即使他们没有Childs也不想满足条件,我想要所有用户。

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

有人有任何建议吗?

1 个答案:

答案 0 :(得分:8)

免责声明:我是该项目的所有者Entity Framework Plus

由于N + 1查询问题,我们的图书馆不支持针对.NET Core的查询过滤器。

在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 Core,相同的投影会使数据库往返以获得每个用户的子项(N + 1个查询)

您可以尝试以下投影,看看是否收到同样的错误。

我相信在EF Core团队修复它之前,据我所知,没有办法过滤子实体。

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

答案子问题:

  

随着.NET Core 2.0的新版本确实解决了这个问题?

不幸的是,Entity Framework仍然无法使用V2.x正确处理强制转换

例如,使用Cast方法的LINQ不起作用:

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

编辑:状态更新

不幸的是,EF Core团队仍未解决投影中的N + 1查询问题。

查看v3.0的最新状态,我认为他们不打算尽快解决此类问题:https://github.com/aspnet/EntityFrameworkCore/issues/10001#issuecomment-456581915