我很难理解为什么我的应用程序的行为方式如此。这是.Net Core中的MVC。我在两个不同的领域有非常相似的代码。一个区域基于给定用户返回结果,而另一个区域基于搜索字符串返回结果。第一部分是基于用户的结果,并按我的意愿工作。
[NonAction]
private IQueryable<Film> GetUserFilms(ApplicationUser user)
{
// Returns all Films of the user that the current User is authorized to see. Audio, Media, and User of the film is included.
return _context.Films
.Include(f => f.Audio)
.Include(f => f.Media)
.Include(f => f.User)
.Where(f => (f.UserID == user.Id) && (!f.IsPrivate || User.IsInRole("Admin") || f.UserID == _userManager.GetUserId(User)));
}
[NonAction]
private List<Film> GetUserFilmsByGenre(ApplicationUser user, string genre = null)
{
// Returns all Films of the user for a specific genre, displaying only those that the current User is authorized to see
return GetUserFilms(user).Include(f => f.FilmGenres).Where(f => f.FilmGenres.Any(fg => fg.Genre.Name == genre)).ToList();
}
[NonAction]
private List<Film> GetUserFilmsByMediaFormat(ApplicationUser user, string mediaFormat = null)
{
// Returns all Films of the user for a specific MediaFormat, displaying only those that the current User is authorized to see
return GetUserFilms(user).Where(f => f.Media.Name == mediaFormat).ToList();
}
下一部分是基于搜索字符串的区域。
[NonAction]
private IQueryable<Film> GetFilmsByTitle(string title)
{
// Returns all Films, containing search parameter, that the current User is authorized to see.
// Audio, Media, FilmGenre.Genre and User of the film are included.
return _context.Films
.Include(f => f.Audio)
.Include(f => f.Media)
.Include(f => f.User)
.Where(f => f.Name.ToLower().Contains(title.ToLower())
&& ((!f.IsPrivate && !f.User.IsPrivate) || User.IsInRole("Admin") || f.UserID == _userManager.GetUserId(User)));
}
[NonAction]
private List<Film> GetAllFilmsByGenre(string title, string genre = null)
{
// Returns all Films, containing the search parameter, for a specific genre,
// displaying only those that the current User is authorized to see
return GetFilmsByTitle(title).Where(f => f.FilmGenres.Any(fg => fg.Genre.Name == genre)).ToList();
}
[NonAction]
private List<Film> GetAllFilmsByMediaFormat(string title, string mediaFormat = null)
{
// Returns all Films, containing the search parameter, for a specific MediaFormat,
// displaying only those that the current User is authorized to see
return GetFilmsByTitle(title).Where(f=> f.Media.Name == mediaFormat).ToList();
}
现在运行GetAllFilmsByMediaFormat方法时,我得到一个nullReferenceException。通过一些测试,我已经确定.Where中的f.Media由于某种原因读取为null。如果我首先分解返回并且只有GetFilmsByTitle(标题),我可以验证Media属性对结果中的每个项都有有效值。我不明白为什么lambda表达式将其视为null。
此外,我在GetAllFilmsByGenre方法上得到nullReferenceException,因为fg.Genre读取为null。
现在,我已经改变了以下内容,将IQueryable更改为List,并将一个Include for FilmGenre和一个ThenInclude for Genre放入我的GetFilmsByTitle方法中。这按预期执行,类似于其他代码在其他部分中的工作方式。
我只想弄清楚为什么会这样?为什么IQueryable在一个实例中是可接受的,而在另一个实例中却不是?当在exectution之前有一个值时,为什么它在lambda表达式中为null?为什么我需要额外的.ThenInclude用于一个查询而不是另一个?
以下是工作代码:
[NonAction]
private List<Film> GetFilmsByTitle(string title)
{
// Returns all Films, containing search parameter, that the current User is authorized to see.
// Audio, Media, FilmGenre.Genre and User of the film are included.
IQueryable<Film> films = _context.Films
.Include(f => f.Audio)
.Include(f => f.Media)
.Include(f => f.User)
.Include(f=> f.FilmGenres)
.ThenInclude(fg=>fg.Genre)
.Where(f => f.Name.ToLower().Contains(title.ToLower())
&& ((!f.IsPrivate && !f.User.IsPrivate) || User.IsInRole("Admin") || f.UserID == _userManager.GetUserId(User)));
return films.ToList();
}
[NonAction]
private List<Film> GetAllFilmsByGenre(string title, string genre = null)
{
// Returns all Films, containing the search parameter, for a specific genre,
// displaying only those that the current User is authorized to see
return GetFilmsByTitle(title).Where(f => f.FilmGenres.Any(fg => fg.Genre.Name == genre)).ToList();
}
[NonAction]
private List<Film> GetAllFilmsByMediaFormat(string title, string mediaFormat = null)
{
// Returns all Films, containing the search parameter, for a specific MediaFormat,
// displaying only those that the current User is authorized to see
return GetFilmsByTitle(title).Where(f=> f.Media.Name == mediaFormat).ToList();