'Collection.AsQueryable() returns NullReferenceException when mapping with AutoMapper
I am still a bit new to programming. I have the following method in my LessonsService:
public async Task<IEnumerable<T>> GetUserLessonsTableDataAsync<T>(string userId, string sortColumn, string sortColumnDirection, string searchValue)
{
var user = await this.usersRepository
.AllAsNoTracking()
.Include(x => x.Trainer)
.ThenInclude(t => t.Lessons)
.Include(x => x.Member)
.ThenInclude(m => m.Lessons)
.ThenInclude(lm => lm.Lesson)
.FirstOrDefaultAsync(x => x.Id == userId);
IQueryable<Lesson> lessons;
if (user.Trainer != null)
{
lessons = user.Trainer.Lessons.AsQueryable();
}
else
{
var lessonsMembers = user.Member.Lessons.Where(x => x.MemberId == user.MemberId);
var lessonsList = new List<Lesson>();
foreach (var lessonMember in lessonsMembers)
{
lessonsList.Add(lessonMember.Lesson);
}
lessons = lessonsList.AsQueryable();
}
var lessonData = from lesson in lessons select lesson;
if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDirection)))
{
lessonData = lessonData.OrderBy(sortColumn + " " + sortColumnDirection);
}
if (!string.IsNullOrEmpty(searchValue))
{
lessonData = lessonData.Where(l => l.Topic.Contains(searchValue)
|| l.StartingTime.Equals(searchValue)
|| l.Group.Name.Contains(searchValue)
|| l.Trainer.User.FirstName.Contains(searchValue)
|| l.Trainer.User.LastName.Contains(searchValue));
}
return lessonData.To<T>().ToList();
}
For some reason this code throws System.NullReferenceException with message "Object reference not set to an instance of an object". I debugged and noticed that lessonData is not null, it is full with data from the database. Apparently, the mapping method .To< T >() is not working properly as it returns the following:

My controller is:
[HttpPost]
public async Task<IActionResult> GetUserLessons()
{
try
{
var userId = this.HttpContext.Session.GetString("userId");
var draw = this.Request.Form["draw"].FirstOrDefault();
var start = this.Request.Form["start"].FirstOrDefault();
var length = this.Request.Form["length"].FirstOrDefault();
var sortColumn = this.Request.Form["columns[" + this.Request.Form["order[0][column]"].FirstOrDefault() + "][name]"].FirstOrDefault();
var sortColumnDirection = this.Request.Form["order[0][dir]"].FirstOrDefault();
var searchValue = this.Request.Form["search[value]"].FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal = 0;
var lessonData = await this.lessonsService.GetUserLessonsTableDataAsync<LessonViewModel>(userId, sortColumn, sortColumnDirection, searchValue);
recordsTotal = lessonData.Count();
var data = lessonData.Skip(skip).Take(pageSize).ToList();
var jsonData = new { draw, recordsFiltered = recordsTotal, recordsTotal, data };
return this.Ok(jsonData);
}
catch (Exception e)
{
throw;
}
}
The exception message in the stack trace is the following:
at System.Linq.Enumerable.SelectIPartitionIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at ChessBurgas64.Services.Data.LessonsService.<GetUserLessonsTableDataAsync>d__15`1.MoveNext() in F:\ChessclubBurgas64WebApp\ChessBurgas64\Services\ChessBurgas64.Services.Data\LessonsService.cs:line 211
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ChessBurgas64.Web.Controllers.UsersController.<GetUserLessons>d__17.MoveNext() in F:\ChessclubBurgas64WebApp\ChessBurgas64\Web\ChessBurgas64.Web\Controllers\UsersController.cs:line 171
I have a static class (where the method .To< T >() is positioned) that is referenced in the lessonsService:
public static class QueryableMappingExtensions
{
public static IQueryable<TDestination> To<TDestination>(
this IQueryable source,
params Expression<Func<TDestination, object>>[] membersToExpand)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
return source.ProjectTo(AutoMapperConfig.MapperInstance.ConfigurationProvider, null, membersToExpand);
}
public static IQueryable<TDestination> To<TDestination>(
this IQueryable source,
object parameters)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
return source.ProjectTo<TDestination>(AutoMapperConfig.MapperInstance.ConfigurationProvider, parameters);
}
}
Inoticed that this happens only to navigational properties (in this case it's user.Trainer.Lessons). If I get the lessons directly from the repository with lessons = this.lessonsRepository.All().Where(...);, there will be no problem and everything will work fine, because the collection will be then a Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable instead of System.Collections.Generic.HashSet`1[Lesson]. So I guess the problem is that the method .AsQueryable() is not really converting the lessons to Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable, which is needed for the mapping method .To< T >() to work properly? What is the best way to fix this?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
