Как добавить несколько аргументов к лямбда в C #

В настоящее время я работаю над проектом по управлению библиотекой. Он имеет 3 таблицы: TblUser, TblBook и TBlBookStatus. Когда пользователь резервирует книгу, идентификатор пользователя из TblUser, идентификатор книги из TblBook сохраняется в другой таблице (TblBookStatus). Я присоединяюсь и создаю новый список в своих таблицах базы данных на c3. Они хранятся в виде списков в моем коде C #. Приведенный ниже код создает список, в котором отображаются зарезервированные книги.

Примечание: я не подключал bookID и userID в качестве внешнего ключа на TblBookStatus по некоторым причинам, связанным с проектом.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LibMan.Models.DB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

namespace LibMan.Pages
{
    public class LibraryModel : PageModel
    {
        private readonly LibMan.Models.DB.LibManContext _context;
        public string Message { get; set; }
        public LibraryModel(LibMan.Models.DB.LibManContext context)
        {
            _context = context;
            DisplayBook = new List<TblBook>();
;        }
        public IList<TblBookStatus> TblBookStatus { get; set; }
        public IList<TblBook> TblBook { get; set; }
        public IEnumerable<TblBook> DisplayBook { get; set; }
        public IList<TblUser> TblUser{ get; set; }

        public async Task OnGetAsync()
        {
            TblBookStatus = await _context.TblBookStatus.ToListAsync();
            TblBook = await _context.TblBook.ToListAsync();
            TblUser = await _context.TblUser.ToListAsync();

            if (TblBookStatus != null && TblBook != null){
                DisplayBook = TblBook.Where(t => TblBookStatus.Any(ts => ts.BookId == t.BookId));            
            }
        }
    }
}

В строке DisplayBook = TblBook.Where(t => TblBookStatus.Any(ts => ts.BookId == t.BookId)); я показываю зарезервированную книгу через bookid, а не по пользователю. Я хочу отображать зарезервированные книги текущего пользователя, вошедшего в систему, а не всех пользователей зарезервированных книг. Итак, есть ли какой-либо способ реализовать это в приведенном выше лямбда-выражении? Я представляю себе что-то подобное, но мой синтаксис неверен.

DisplayBook = TblBook.Where(t => TblBookStatus.Any(ts => ts.BookId == t.BookId),a=> TblUser.Any(as=> as.UserId == a.UserId);

Спасибо за помощь!


person Fuzzyy    schedule 25.05.2020    source источник


Ответы (3)


{РЕДАКТИРОВАТЬ - ответ был отмечен как правильный, поскольку поведение было указано, но технически не отвечало на вопрос}

Чтобы ответить на вопрос: «Как добавить несколько аргументов в лямбда-выражение в C #», важно понимать, что в этом случае лямбда-выражение преобразуется в тип делегата, определенный как параметр для методов linq, таких как Where() и Any(). Следовательно, lamda должна соответствовать «сигнатуре» типа делегата, которая определяет его параметры и возвращаемое значение. В большинстве случаев методы linq ожидают делегата с именем Predicate, определенным как delegate bool Predicate<in T>(T obj). Следовательно, преобразованная лямбда должна получить один параметр типа T, являющийся типом элемента Enumerable, и вернуть одно логическое значение.

Таким образом, вы не можете добавлять аргументы в лямбда-выражение, которые должны быть преобразованы в делегаты, это тип делегата, который определяет параметры и тип возвращаемого значения. Лямбда с "несколькими аргументами" может выглядеть так, в соответствии с подписью делегата divide, два int на входе, один double на выходе:

Func<int, int, double> divide = (x, y) => { return x / y; };

Чтобы обеспечить требуемое поведение, вы можете рассмотреть альтернативный подход:

(У меня нет ваших моделей для тестирования, поэтому рассмотрите этот псевдо, но, глядя на ваш запрос, вы можете попробовать что-то вроде ...)

var DisplayBook =  (from book in TblBook
                    from bookStatus in TblBookStatus
                    from user in TblUser
                    where (book.BookId == bookStatus.BookId) && (user.UserId == currentReader) && (user.UserId == bookStatus.ReservedBy)
                    select book).FirstOrDefault();
person George Kerwood    schedule 25.05.2020
comment
Можете ли вы предложить способ получить идентификатор пользователя из сеанса в currentReader? - person Fuzzyy; 25.05.2020
comment
Боюсь, что не могу из того, что вы здесь предоставили. Возможно, вы зададите еще один вопрос с подробностями о том, как вы в настоящее время входите в систему :) - person George Kerwood; 25.05.2020
comment
Привет, я действительно нашел способ и попробовал это, но на странице ничего не отображается. Можете ли вы мне помочь, если я предоставлю дополнительную информацию? - person Fuzzyy; 25.05.2020
comment
Я использовал var UserEmail = HttpContext.Session.GetString("Email"); для получения электронной почты текущего пользователя, вошедшего в систему, и я уверен, что он не возвращается как null, я распечатал его на консоли, но когда я использую решение, которое вы предоставили выше, у меня ничего не отображается на странице. - person Fuzzyy; 25.05.2020
comment
Решено! Я удалил var decleration перед DisplayBook, потому что я уже объявил и инициализировал его раньше, он действовал как локальная переменная. Это не то, чего требует название, но я отмечаю это как решение. Спасибо! - person Fuzzyy; 25.05.2020
comment
@Fuzzy, Рад, что ты в порядке. Я отредактировал свой ответ, на самом деле отвечаю на ваш вопрос, так как вы отметили его как решенное. Таким образом, это может оказаться полезным и для других. - person George Kerwood; 26.05.2020

Почему бы просто не присоединиться к наборам данных по UserId?

DisplayBook = (from book in TblBook
               join stat in TblBookStatus
               on book.BookId equals stat.BookId
               join usr in TblUser
               on stat.UserId equals usr.UserId
               where usr.UserId = <currentUserId>
               Select book).ToList();
person Kedar    schedule 25.05.2020
comment
Когда я вставил это в свой код, я получаю сообщение об ошибке: ** Тело запроса должно заканчиваться предложением select или предложением group. ** Как я могу это исправить? Я новичок в этом, поэтому спасибо за помощь. - person Fuzzyy; 25.05.2020
comment
Это также требует дополнительной работы для фильтрации по CurrentUser. - person George Kerwood; 25.05.2020
comment
изменил where usr.UserId = <currentUserId> на where usr.UserId == <currentUserId>, и это тоже сработало, спасибо за помощь! - person Fuzzyy; 25.05.2020
comment
@Kedar @Fuzzyy Мне нравится этот ответ, так как он использует join. Это более стандартный и правильный подход к работе со структурами таблиц. - person George Kerwood; 26.05.2020

Попробуй это :

//assumuning current userid is in below variable.
int CurrentUserId;// Fetch it from Session object if you store userid on login

DisplayBook = TblBook.Where(t => TblBookStatus.Any(ts => ts.BookId == t.BookId)
              && TblUser.Any(tb=>tb.UserId==CurrentUserId && tb.BookId==t.BookId)); 
person Ajay Kelkar    schedule 25.05.2020
comment
Я думаю, что, возможно, самое последнее выражение может быть неправильным, поскольку элементы TblUser не будут иметь свойства BookId, если я правильно понял? Должно быть _2 _? @ AjayKelkar - person George Kerwood; 25.05.2020
comment
TblBook присоединяется к TblBookStatus BookId, присоединяется к UserTbl UserId - person George Kerwood; 25.05.2020
comment
Вы правы, @GeorgeKerwood, у меня нет BookId на TblUser. - person Fuzzyy; 25.05.2020