Base solution for your next web application
Open Closed

WhereIf not including Property #7184


User avatar
0
Dom1702 created

Hi,

I have the following part of code:

 var filteredDrivingLessons = _drivingLessonRepository.GetAllIncluding(e => e.Instructors) // Instructors is a list for a many-to-many relationship
                        .WhereIf(!string.IsNullOrWhiteSpace(input.InstructorFilter), e => ContainsInstructor(e, input.InstructorFilter));

When debugging filteredDrivingLessons, the Instructors array is available and not null.

In the ContainsInstructor method however, the Instructors array is null. Why is that so?

What I am trying to achieve is passing an instructorFilter string that checks every entry in the Instructors array and compares first and last name.

Is there something in the WhereIf extension method not working as I expect it to or am I doing something completely wrong here?

Thank you!


7 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Since the query has not yet been executed, you know that iqueryable is a delayed query. The expression will be translated into a sql statement.

    Your code can't be translated into sql statement first. If you don't want to translate it into sql, it might look like the following code.

    var filteredDrivingLessons = _drivingLessonRepository.GetAllIncluding(e => e.Instructors).ToList()
    .WhereIf(!string.IsNullOrWhiteSpace(input.InstructorFilter), e => ContainsInstructor(e, input.InstructorFilter));
    

    If you want to execute in the database, you can put the code in the ContainsInstructor method into the lambda expression (WhereIf).

    If it still can't be solved, please share your code.

  • User Avatar
    0
    Dom1702 created

    Hi Maliming,

    thanks for your help. This is the code:

     private bool ContainsInstructor(DrivingLesson dl, string filter)
            {
                if(dl.Instructors == null) // This is the part I always end up even though there are Instructors available
                    return false;
            
                for (int i = 0; i < dl.Instructors.Count; i++)
                {
                    if (dl.Instructors[i].Instructor.FirstName.Equals(filter) || dl.Instructors[i].Instructor.LastName.Equals(filter))
                        return true;
                }
    
                return false;
            }
    

    And this is the actual method:

     public async Task<PagedResultDto<GetDrivingLessonForViewDto>> GetAll(GetAllDrivingLessonsInput input)
             {
    
                var filteredDrivingLessons = _drivingLessonRepository.GetAllIncluding(e => e.Instructors)
                            .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), e => false || e.Topic.Contains(input.Filter))
                            .WhereIf(input.MinLengthFilter != null, e => e.Length >= input.MinLengthFilter)
                            .WhereIf(input.MaxLengthFilter != null, e => e.Length <= input.MaxLengthFilter)
                            .WhereIf(input.MinStartTimeFilter != null, e => e.StartTime >= input.MinStartTimeFilter)
                            .WhereIf(input.MaxStartTimeFilter != null, e => e.StartTime <= input.MaxStartTimeFilter)
                            .WhereIf(input.CompletedFilter > -1, e => Convert.ToInt32(e.Completed) == input.CompletedFilter)
                            .WhereIf(input.DrivingLessonTopicTopicFilter != null, e => e.Topic.Contains(input.DrivingLessonTopicTopicFilter))
                            .WhereIf(!string.IsNullOrWhiteSpace(input.InstructorFilter), e => ContainsInstructor(e, input.InstructorFilter));
    
                var query2 = (from o in filteredDrivingLessons
    
                              select new GetDrivingLessonForViewDto()
                              {
                                  DrivingLesson = ObjectMapper.Map<DrivingLessonDto>(o),
                                  StudentFullName = (o.StudentFk.FirstName == null || o.StudentFk.LastName == null) ? "" : o.StudentFk.FirstName + " " + o.StudentFk.LastName,
                                  Description = o.Description,
                                  Instructors = ObjectMapper.Map<IList<Instructors.Dtos.InstructorDto>>((from i in o.Instructors
                                                                                                         join i2 in _lookup_instructorRepository.GetAll() on i.InstructorId equals i2.Id
                                                                                                         select new Instructor() { Id = i2.Id, FirstName = i2.FirstName, LastName = i2.LastName }).ToList())
                              })
                            .WhereIf(!string.IsNullOrWhiteSpace(input.LicenseClassClassFilter), e => e.DrivingLesson.LicenseClass != null && e.DrivingLesson.LicenseClass.ToLower() == input.LicenseClassClassFilter.ToLower().Trim());
    
    
                var totalCount = await query2.CountAsync();
    
                var drivingLessons = await query2
                    .OrderBy(input.Sorting ?? "drivingLesson.id asc")
                    .PageBy(input)
                    .ToListAsync();
    
                return new PagedResultDto<GetDrivingLessonForViewDto>(
                    totalCount,
                    drivingLessons
                );
             }
    

    Thanks for your help. I really have no idea how to add this array to the query in way that I don't get the NullReferenceException.

    I also tried to use the id in the ContainsInstructor method to get that one driving lesson from the repository, however then I get an exception telling me that I can't nest this query in another query because ef core does not allow this.

  • User Avatar
    0
    maliming created
    Support Team

    hi @Dom1702

    Can you simply implement the above situation using the Zero Demo project?

    Then send the project to me, [email protected]

  • User Avatar
    0
    Dom1702 created

    I'm not sure, what you mean.

    What part of the project do you need?

  • User Avatar
    0
    maliming created
    Support Team

    You can create a Demo project, and then simply implement the above entities and code in the Demo project. After sending the project to me, I can try to help you solve the problem.

  • User Avatar
    0
    Dom1702 created

    Ah ok, it's not a big deal to upload my current project. Not much done. Can I just zip angular and asp net backend folders, upload it on my space and send you a link via mail?

  • User Avatar
    0
    maliming created
    Support Team

    Yes, you can send it to my mailbox.