C#Lambda表达式查询参数使用IQueryable读取为null,但是与List一起使用?

时间:2017-07-06 17:42:35

标签: c# asp.net-mvc

我很难理解为什么我的应用程序的行为方式如此。这是.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();

0 个答案:

没有答案