计算表中包含给定项的记录

时间:2017-05-30 19:07:08

标签: c# entity-framework

我的查询应该计算包含给定流派的所有电影。

查询有效,但它查询数据库中每部电影的链接表,导致1分钟和6秒的加载时间。

表结构如下所示:

电影 包含所有电影

类型 包含所有类型的名称

MovieGenre 此表中的每条记录都包含电影ID和流派名称。

 public async Task<int> CountMovies(List<string> pGenres)
    {
        return await (
            from movie in Context.Movie
            join genre in Context.MovieGenre on movie.MovieId equals genre.MovieId into genres
            where pGenres.All(pGenre => genres.Any(genre => genre.GenreName == pGenre))
            select movie
        ).CountAsync();
    }

如何防止往返服务器并在数据库中执行所有操作?

上面的代码导致108次往返数据库,例如:

SELECT [genre0].[genre_name],[genre0].[movie_id]
FROM [Movie_Genre] AS [genre0]
WHERE 353 /* @_outer_MovieId */ = [genre0].[movie_id]

6 个答案:

答案 0 :(得分:0)

首先将您的流派列表插入临时表,然后加入

答案 1 :(得分:0)

如果Context.MovieGenre的类型为MovieGenres,并且它包含单个MovieGenre对象的集合,则添加扩展方法:

int CountMoviesWithGenre(this MovieGenres mg, List<string> genreNames)
{
    return mg
       .Where(mg=>genreNames.Contains(mg.GenreName,
                   StringComparison.InvariantCultureIgnoreCase))
       .Select(m => m.MovieId)
       .Distinct()
       .Count();
}

这样称呼:

var genNames = new List<string> {"Horror", "Suspense","Action"};
var count = Context.MovieGenre.CountMoviesWithGenre(genNames);

答案 2 :(得分:0)

EF Core仍然存在将复杂查询转换为sql的一些问题,它将服务器执行与客户端执行混合在一起,并且查询中有一些内容正在客户端执行。而不是执行count(*)正在加载所选电影的所有数据。要尝试改进查询,请尝试以下操作:

return await Context.MovieGenre.GroupBy(e=>e.MovieId,e=>e.GenreName)
                               .Where(g=>pGenres.All(pGenre => g.Contains(pGenre)))
                               .CountAsync();

主要问题是Where条件,您还可以尝试以下操作:

  return await Context.MovieGenre.Where(g=>pGenres.Contains(g.GenreName))
                                 .GroupBy(e=>e.MovieId,e=>e.GenreName)
                                 .Where(g=>pGenres.Count==g.Count())
                                 .CountAsync();

答案 3 :(得分:0)

我已经完成了。

        public async Task<int> CountMovies(List<string> pGenres, int? year, decimal? minPrice,
        decimal? maxPrice)
    {
        using (var command = Context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = $"SELECT COUNT(DISTINCT Movie.movie_id) from Movie_Genre join Movie on Movie.movie_id = Movie_Genre.movie_id where genre_name in ('Action', 'Adult')";
            Context.Database.OpenConnection();
            using (var result = command.ExecuteReader())
            {
                await result.ReadAsync();
                int amount = result.GetInt32(0);
                Context.Database.CloseConnection();
                return amount;
            }
        }
    }

答案 4 :(得分:0)

我最近看过/使用的一个很好的技巧是你可以告诉你很多:

public async Task<int> CountMovies(List<string> pGenres) {
    return await (
        from movie in Context.Movie
        join genre in Context.MovieGenre on movie.MovieId equals genre.MovieId into genres
        where genres.Where(genre => pGenres.Contains(genre.GenreName)).Count() == pGenres.Count()
        select movie
    ).CountAsync();
}

答案 5 :(得分:-1)

这是一次旅行,并返回至少包含一个pGeners的所有电影。

var moviesCount = Context.MovieGenre
             .Where(x => pGenres.Contains(x.GenreName))
             .Select(x => x.Movie).Distinct().ToList().Count();