Linq to Entities in Clause to many to Many

时间:2012-08-23 00:41:54

标签: c# linq entity-framework entity entity-relationship

我正在尝试使用Where in子句与linq一起使用实体并遇到问题。我的问题是我有几个不同实体的列表,我想从这些列表中选择一组游戏实体,基本上为它们设置一个SQL WHERE IN子句。问题在于将实体列表与具有多对多关系的游戏实体的相关实体进行比较。我已经做了很多研究并尝试了一些解决方案来解决这个问题,但是不能正确地解决这个问题,我非常感谢stackoverflow社区的一些帮助。

提前致谢。

编辑:

我试过这样做而不是工会:

     var relatedGames = from game in ugdb.Games
                        where game.Developers.Any(d => relatedDevelopers.Any(r => r.DeveloperID == d.DeveloperID))
                        || game.Publishers.Any(d => relatedPublishers.Any(r => r.PublisherID == d.PublisherID))
                        || game.Genres.Any(d => relatedGenres.Any(r => r.GenreID == d.GenreID))
                        select game;

对于这两个联盟,我收到以下错误消息:

base {System.SystemException} = {“无法创建类型'UltimateGameDB.Domain.Entities.Developer'的常量值。在此上下文中仅支持基本类型(例如Int32,String和Guid') 。“}

有没有人知道如何在没有

的情况下这样做

我目前的代码:

  public IQueryable<Video> GetSimilarVideos(Guid videoId)
  {
     IQueryable<Video> result = null;
     List<Video> similarVideoList = null;

     Video currentVideo = ugdb.Videos.Find(videoId);

     List<Genre> relatedGenres = new List<Genre>();
     List<Developer> relatedDevelopers = new List<Developer>();
     List<Publisher> relatedPublishers = new List<Publisher>();

     foreach (var game in currentVideo.Games)
     {
        relatedDevelopers.AddRange(game.Developers);
        relatedPublishers.AddRange(game.Publishers);
        relatedGenres.AddRange(game.Genres);
     }

     relatedDevelopers = relatedDevelopers.Distinct().ToList<Developer>();
     relatedPublishers = relatedPublishers.Distinct().ToList<Publisher>();
     relatedGenres = relatedGenres.Distinct().ToList<Genre>();

     //This is the piece I am having trouble with!
     var relatedGames = from game in ugdb.Games
                        where game.Developers.Union(relatedDevelopers).Count() > 0
                          || game.Genres.Union(relatedGenres).Count() > 0
                          || game.Publishers.Union(relatedPublishers).Count() > 0
                        select game;

     foreach (var game in relatedGames)
     {
        similarVideoList.AddRange(game.Videos.Where(v => v.VideoType.Equals(currentVideo.VideoType)));
     }

     result = similarVideoList.Distinct().AsQueryable<Video>();

     return result;
  }

2 个答案:

答案 0 :(得分:3)

你无法传递本地实体 - 它们不会转换为sql,在你的案例中是相关的开发者。 Linq to Entities无法将relatedDevelopers.Contains转换为Sql IN

您可以投射游戏列表并在内存中进行调用,这样就不必将其转换为sql - 这更容易,但如果您的数据库很大,那么加载它可能会很糟糕,只需添加ToList()

末尾的ugdb.Games
 var relatedGames = from game in ugdb.Games.ToList()
                    where game.Developers.Any(d => relatedDevelopers.Any(r => r.DeveloperID == d.DeveloperID))
                    || game.Publishers.Any(d => relatedPublishers.Any(r => r.PublisherID == d.PublisherID))
                    || game.Genres.Any(d => relatedGenres.Any(r => r.GenreID == d.GenreID))
                    select game;

或者,您可以创建Id的列表并传递它,因为这是SQL可以识别的基本类型:

     var relatedDevelopers = currentVideo.Games.SelectMany( g => g.Developers ).Select( g => g.DeveloperID ).ToArray();
     var relatedPublishers = currentVideo.Games.SelectMany( g => g.Developers ).Select( g => g.DeveloperID ).ToArray();
     var relatedGenres = currentVideo.Games.SelectMany( g => g.Developers ).Select( g => g.DeveloperID ).ToArray();


     //This is the piece I am having trouble with!
     var relatedGames = from game in ugdb.Games
                        where game.Developers.Any( d => relatedDevelopers.Contains(d.DeveloperID) )
                        || game.Publishers.Any( d => relatedPublishers.Contains(d.PublisherID))
                        || game.Genres.Any( d => relatedGenres.Contains(d.GenreID) )
                        select game;

答案 1 :(得分:2)

该模式通常使用嵌套AnyAny Contains

var relatedDeveloperIds = relatedDevelopers.Select(r => r.Id).ToList();
game.Developers.Any(d => relatedDeveloperIds.Contains(d.Id))