使用Linq

时间:2017-06-15 11:19:13

标签: c# sql asp.net entity-framework linq

我正在尝试获取满足List<int>中包含的所有genreIds的gameIds列表。

表格(部分):

editorial_list:

  • game_id
  • 含量

game_genres(游戏可以属于多种类型):

  • ID
  • game_id
  • genre_id

我需要获取game_genres表中所有genre_id的游戏ID列表。

例如:

genre_id的列表包括流派2和3。

如果game_genres = 2和genre_id = 3,genre_id表中存在游戏ID = 14,那么它将包含在最终结果中。

这是我的代码:

 // get the list of game_id's that have an editorial
 var editorialList = (from ee in db.editorials where ee.is_enabled == true select new {
     game_id = ee.game_id
 }).ToList();

// Produce a list of the games in the editorials and their genre Ids that the belong to
 var gameAndGenres = (from el in editorialList join gg in db.game_genres
  on el.game_id equals gg.game_id

     select new {
         game_id = el.game_id,
             genre_id = gg.genre_id
     }
 );

 var res = gameAndGenres.Where(
  x => x.genres.Contains(x.genre_id)) == genres.Count; // stuck here

最终结果应该是game_id的唯一列表,列表中的每个游戏都属于所有类型中列出的类型{ {1}}。

我创建了几个步骤来帮助我理解查询,但它可以在一行中解决,我只是无法解决它。

更新:这是我尝试的新代码。

List<int>

3 个答案:

答案 0 :(得分:2)

游戏和流派之间的关系是多对多的:Game可以属于零个或多个流派,Genre可以有零个或多个游戏。

您想要game-genres表格中属于所有类型的所有游戏(的ID)。

例如,如果您的列表游戏类型仅包含对类型2和类型3的引用的记录,那么您需要所有属于类型2和3的游戏。

请注意,Genre可能存在并非任何“游戏”拥有。在这种情况下,游戏类型表中没有记录,并且引用了此Genre

下面是您的Property Entity Framework类的示例。类和属性的实际名称可能有所不同,但您将获得Id

public class Game
{
    public int GameId {get; set;}
    public virtual ICollection<Genre> Genres {get; set;}
    ... // other properties
}
public class Genre
{
    public int GenreId {get; set;
    public virtual ICollection<Game> Games {get; set;}
    ...
}
public MyDbContext : DbContext
{
    public DbSet<Game> Games {get; set;}
    public DbSet<Genre> Genres {get; set;}
    ...
}

实体框架模型构建器将检测到游戏和流派之间存在多对多关系,并将自动添加类似您的游戏类型的表格。

好消息是,如果某个类型不属于任何游戏,它就不会出现在你的game_genres表中。反过来说:如果你的游戏类型表中有一个元素,那么至少有一个属于该类型的游戏。

所以你不想要所有类型,你只需要至少有一个Game使用的类型。

IEnumerable<Genre> usedGenres = dbContext.Genres
    .Where(genre => genre.Games.Any());

现在,您只需要Games中属于每种类型的usedGenresIEnumerable<int> usedGenreIds = usedGenres .Select(genre => genre.GenreId); IEnumerable<Game> gamesWithAllUsedGenres = dbContext.Games .Where(game => usedGenreIds.All(genreId => game.Genres.Select(genre => genre.GenreIdContains(genreId)); =每个游戏,其中usedGenres的每个元素都在Game.Genres集合中。

要检查类型是否在Game.Genres的集合中,我们只需将Game.Genres的GenreId与usedGenreIds的GenreId进行比较

var elmt = gridTestUtils.dataCell('grid1', <row>, <col>);

答案 1 :(得分:2)

这样的事情:

        var gamesIds = db.editorials
            .Where(e => db.game_genres.Select(gg => gg.genre_id).Distinct().All(genId => db.game_genres.Any(gg => gg.game_id == e.game_id && gg.genre_id == genId)))
            .Select(e => e.game_id)
            .ToList();

从社论中选择game_id,其中game_id在game_genre表中包含所有不同genre_id的条目。

如果您希望所有类型的游戏都在列表中而不是表格中的所有类型:

List<int> genreIds = new List<int>() {1,2,3};

    var gamesIds = db.editorials
        .Where(e => genreIds.All(genId => db.game_genres.Any(gg => gg.game_id == e.game_id && gg.genre_id == genId)))
        .Select(e => e.game_id)
        .ToList();

答案 2 :(得分:0)

你可以通过灌输表格中的行来实现它。

使用Lambda表达式:

var res = db.game_genres.GroupBy(gg => gg.game_id)
    .Where(g => g.Count() == db.genres.Count())
    .Select(x => x.Key).ToList();

或使用LINQ:

 var res = (from gg in db.game_genres
             group gg by gg.game_id into g
             where g.Count() == db.genres.Count()
             select g.Key).ToList();

这种灌注每game_id产生一条记录(称为组)。每个组的Key是&#34;组中使用的game_id&#34;条款。每个组都是具有相同game_id的行的集合,因此您可以将其视为任何其他数据库实体集合,在此处使用where语句对其进行过滤,并在集合上调用Count()