使用Linq获取匹配ID列表的结果
我想要获得满足所有genreIds包含在List<int>
中的gameIds列表。使用Linq获取匹配ID列表的结果
的表(部分):
editorial_list:
- game_id
- 内容
game_genres(游戏可以属于多个流派):
- ID
- game_id
- genre_id
我需要存在在game_genres表中的所有genre_id
的游戏的游戏ID的列表。
例如:
的genre_id
列表的包括类型2和3
如果游戏ID = 14存在于game_genres
表两者genre_id
= 2和genre_id
= 3。因此,它将被包含在最终结果中。
这里是我的代码:
// 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的独特的列表,在列表每场比赛属于所有这是在体裁List<int>
列出的流派。
我创建了几个步骤来帮助我理解查询,但它可能能够在一行中解决,我只是无法解决它。
更新:这是我尝试的新代码。
var res = gameAndGenres.GroupBy(x => x.game_id)
.Select(g => new {
game_id = g.Key,
genreIds = g.Select(c => c.genre_id)
});
var res2 = res.Where(x => genres.Intersect(x.genreIds).Count()
== genres.Count()).ToList();
游戏和流派之间的关系是一个多到多:一个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());
现在你想只有那些属于每一个流派在usedGenres
Games
=每场比赛,其中usedGenres的所有元素都在收集Game.Genres。
要检查一个流派是Game.Genres的集合中,我们只需要在GenreId与usedGenreIds的GenreId比较Game.Genres的
IEnumerable<int> usedGenreIds = usedGenres
.Select(genre => genre.GenreId);
IEnumerable<Game> gamesWithAllUsedGenres = dbContext.Games
.Where(game => usedGenreIds.All(genreId => game.Genres.Select(genre => genre.GenreIdContains(genreId));
您可以通过从groupping行实现它你表。
使用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();
这种grouppin*生每game_id
一个记录(称为组)。每组的Key
是在“group by”子句中使用的game_id
。每个组是具有相同game_id
行的集合,所以你可以把它像数据库实体的任何其他集合,在这里你使用where
声明其过滤和收集调用Count()
。
事情是这样的:
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_GENRE表中的所有不同genre_ids进入选择game_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();
在哪里使用具有该游戏应该遵守,以 –
阿余did't明白你的问题,你想有所有类型列表中的所有游戏类型的列表清单
现在看看编辑的答案。 –
因为game_genres有流派的所有GAEMS这将是非常不见效,我只是希望那些谁有编辑内容。 –