LINQ Multiple "||" с оператором "&" - PullRequest
       16

LINQ Multiple "||" с оператором "&"

1 голос
/ 21 апреля 2020

У меня следующий запрос Linq, пытающийся отфильтровать коллекцию результатов, удовлетворяющих определенным условиям, следующим образом:

public async Task<BillListResponse> GetStudentCurrentBillsAsync(Student student)
    {
        var studentEvents = student.StudentEvents;
        var studentServices = student.StudentServices;
        var studentGroups = student.StudentGroups;

List<Bill> currentBills = await _context.Bills
            .Include(b => b.Category)
            .Where(b => ((b.ClassBills.Any(c => c.StudentClassId == student.ClassId)) || studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId) || studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId)) && b.SessionId == currentSession.Id
                ).ToListAsync();
......

Но я продолжаю получать следующую ошибку

InvalidOperationException: Выражение LINQ 'DbSet .Where (b => DbSet .Where (c => EF.Property> (b, "Id")! = Null && EF.Property> (b, "Id") == EF. Свойство> (c, "BillId")) .Any (c => c .StudentClassId == __student_ClassId_0) || __student_StudentEvents_1 .Any (se => (Nullable) se.EventId == b.EventId) | | > EF.Property> (b, "Id")! = Null && EF.Property> (b, "Id") == EF.Property> (c0, "BillId")) .Any (c0 => (Nullable) c0.CareerPathId == __student_CareerPathId_4) && b.SessionId == __currentSession_Id_5) 'не удалось перевести. Либо переписать запрос в форме, которую можно перевести, либо явно переключиться на оценку клиента, вставив вызов либо AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsyn c ().

, который я не смог разрешить. Тем не менее, я понял, что если удалить "||" предложения в выражении, а именно:

List<Bill> currentBills = await _context.Bills
            .Include(b => b.Category)
            .Where(b => b.ClassBills.Any(c => c.StudentClassId == student.ClassId) && b.SessionId == currentSession.Id
                ).ToListAsync();

, это работает, но мне нужно больше условий, как указано в полном выражении.

Я работаю на ASP. NET -Core 3.1 на Windows с SQL База данных сервера.

Кажется, я что-то не так с "||" оператор.

Пожалуйста, помогите мне решить эту проблему. Я буду признателен.

Спасибо

ОБНОВЛЕНИЕ


Отношения сущностей таковы:

Студенческая сущность имеет следующие значения

public virtual ICollection<StudentGroup> StudentGroups { get; set; }
public virtual ICollection<StudentService> StudentServices { get; set; }

public virtual ICollection<StudentEvent> StudentEvents { get; set; }

И следующие наборы данных DbSets существуют также

public DbSet<StudentGroup> StudentGroups { get; set; }
public DbSet<StudentEvent> StudentEvents { get; set; }
public DbSet<SpecialService> Services { get; set; }

И промежуточные таблицы "многие ко многим" имеют следующий вид:

public class StudentEvent
{
    public string StudentId { get; set; }
    public int EventId { get; set; }

    [ForeignKey("StudentId")]
    public Student Student { get; set; }
    [ForeignKey("EventId")]
    public SchoolEvent Event { get; set; }
}

public class StudentService
{
    public int SpecialServiceId { get; set; }
    public virtual SpecialService Service { get; set; }
    public string StudentId { get; set; }
    public virtual Student Student { get; set; }
}

public class StudentGroup
{
    public int SpecialGroupId { get; set; }
    public virtual SpecialGroup SpecialGroup { get; set; }
    public string StudentId { get; set; }
    public virtual Student Student { get; set; }
}

ОБНОВЛЕНИЕ

Я изменил запрос следующим образом, и он, кажется, работает сейчас.

var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();

List<Bill> bills = await (from b in _context.Bills where b.ClassBills.Any(c => c.StudentClassId == student.ClassId) || (studentEvents.Any() && studentEvents.Any(se => se.EventId == b.EventId)) || (studentGroups.Any() && studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId)) || (studentServices.Any() && studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId)) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId) select b).ToListAsync();

Другой способ, который, кажется, работает как ожидалось, следующий

var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();

var currentBills = _context.Bills
            ?.Include(b => b.Category)
            ?.Include(b => b.ClassBills)
            ?.Include(b=>b.CareerPathBills)
            ?.Where(b => b.SessionId == currentSession.Id);

        if (student.StudentEvents.Any())
        {
            currentBills = currentBills.Where(b => student.StudentEvents.Any(se => se.EventId == b.EventId));
        }

        if (student.StudentServices.Any())
        {
            currentBills = currentBills.Where(b => student.StudentServices.Any(se => se.SpecialServiceId == b.ServiceId));
        }

        if (student.StudentGroups.Any())
        {
            currentBills = currentBills.Where(b => student.StudentGroups.Any(se => se.SpecialGroupId == b.GroupId));
        }

        var currentBillsList = await currentBills.ToListAsync();

И

currentBillsList

- ожидаемый результат для возврата

Я не уверен, является ли это правильным подходом.

1 Ответ

0 голосов
/ 21 апреля 2020

Причина сбоя заключается в том, что коллекция students может не входить в запрос SQL для таблиц базы данных, т. Е. При вызове ToList или ToListAsync она становится C# коллекция сущностей и не будет работать с коллекциями LINQ to Entities.

Подсказка: убедитесь, что ваши students являются коллекциями IQuerable.

Однако, поскольку В качестве альтернативы вы можете использовать Join Студенты и счета вместо использования фильтрации в предложении Where.

...