2017-04-18 78 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

當/如果他們解決了這個問題,_ **請** _返回並更新這個答案! –