簡體   English   中英

LINQ - EF Core - 返回 object 在嵌套列表中包含兩個對象(由屬性引用)

[英]LINQ - EF Core - Return object that contains two objects (referenced by property) in nested list

我知道有一百萬個 LINQ 問題,所以很抱歉問這個問題。 我環顧四周,我找不到正確的答案。 我懷疑這很容易,但我是 LINQ 和 EF 內核的新手。

我有以下從數據庫查詢返回的 Room 類型列表(為簡潔起見,我只包括一個):

[
    {
        "roomId": 2,
        "roomName": "test",
        "users": [
            {
                "userId": 2,
                "username": "seconduser",
                "password": "demo",
                "token": null,
                "refreshToken": null,
                "alias": "test",
                "friends": null
            },
            {
                "userId": 3,
                "username": "thirduser",
                "password": "demo",
                "token": null,
                "refreshToken": null,
                "alias": "test",
                "friends": null
            }
        ]
    }
]

偉大的。 我想要一個 LINQ 查詢(最好是流利的語法,但我很感激任何幫助),它將用更多房間查詢這個列表並只返回一個(我知道只有一個)滿足以下標准:

房間里只有兩個用戶,並且這兩個用戶都是通過傳入方法的 userId 來標識的。

因此,如果方法接收到以下 object:

{
    "friendId": 1,
    "requestUserId": 3
}

上面引用的房間將被退回,其他房間不退還。

我希望這很清楚。

提前致謝!

編輯 - 很公平,我現在包括一些讓我更接近的嘗試

我嘗試填充兩個用戶,以便我可以詢問 room.Users.Contains() 是否像這樣:

var requestingUser = UserService.GetSingleUser(request.RequestUserId);
            
var friendUser = UserService.GetSingleUser(srequest.FriendId);

var test = allRooms.FirstOrDefault(room => room.Users.Count == 2 && room.Users.Contains(friendUser) && room.Users.Contains(requestingUser);

然而,用戶的比較並沒有通過 go。 這只是我如何填充用戶的問題嗎? 無論如何,我知道我不應該那樣做。

然后我嘗試了在方向方面似乎是正確的方法,就像這樣比較 ID:

var test = allRooms.First(room => room.Users.Any(user =>
    user.userId == request.FriendId && user.userId == request.RequestUserId));

但這會返回 null,但我已經確認有一個房間滿足我指定的條件。

給我帶來麻煩的是 EF 核心生成了一個我不熟悉的數據庫模式。 僅在 SQL 中,我將有表 ROOM、USER、ROOMUSER 和內部加入 ROOMUSER,其中 USER.id 都存在......並且不同,或者類似的東西。

進一步編輯:

我在下面包含了我用來構建數據庫的模型。 最初我沒有,因為我包含的 JSON 是查詢所有房間並包括其用戶(房間內的 ICollection)的結果。

    public class User
    {
        public int UserId { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string Token { get; set; }
        public string RefreshToken { get; set; }
        public string Alias { get; set; }
        
        public ICollection<User> Friends { get; set; }
    }

    public class Room
    {
        public int RoomId { get; set; }
        public string RoomName { get; set; }
        
        public ICollection<User> Users { get; set; }
    }

因此,正如我所描述的,如果我手工制作表格會是什么樣子,這個想法是 User 和 Room 是不同的實體(主要實體),並且會有一個連接表格來暗示它們之間的關系。 從概念上講,用戶在房間中。

以下 LINQ 返回的初始 JSON 也可能使事情更清楚:

var allRooms = db.Rooms.Include(x => x.Users).ToList();

因此,要求具有上述條件的房間應該不會太難。

誠然,正如我所說,我從未使用過 EF 內核,也幾乎沒有使用過 LINQ。 我可能犯了一個愚蠢的錯誤......

這個很近

room => room.Users.Any(user =>
    user.userId == request.FriendId && user.userId == request.RequestUserId)

但需要一些調整

  • 並且 ( && ) 運算符不合適 - id 不能同時等於兩個傳遞的 id。 它應該是一個或另一個,即您需要的是 Or ( || ) 運算符

    user.userId == request.FriendId || user.userId == request.RequestUserId

  • Any也不合適。 它將返回一個房間,其中只有一個通過的用戶,或兩者兼有,但其中還有其他用戶。 你需要的是All

    room.Users.All(user => user.userId == request.FriendId || user.userId == request.RequestUserId)

然而All也為空集返回 true(即當room.Users為空時),所以它必須與另一個調用結合以消除這種情況

room.Users.Any() && room.Users.All(user =>
    user.userId == request.FriendId || user.userId == request.RequestUserId)

這將產生所需的結果,但效率低下,因為涉及兩個子查詢而不是一個。

因此,最好的辦法是使用我所說的“條件計數”並將結果計數與兩 (2) 進行比較:

room.Users.Count(user =>
    user.userId == request.FriendId || user.userId == request.RequestUserId) == 2

也可以用這樣的輸入更通用地表達(因為它支持超過 2 個)

// could contain more than two ids and doesn't need to be array
var userIds = new [] { request.FriendId, request.RequestUserId }.AsEnumerable();

和查詢條件如

room.Users.Count(user => userIds.Contains(user.userId)) == userIds.Count()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM