简体   繁体   English

在许多子句中对实体的限制

[英]Linq to Entities Where In Clause Many to Many

I am trying to get a Where In clause to work with linq to entities and have run into problems. 我正在尝试使用Where In子句来与linq一起使用到实体,并遇到了问题。 My issue is that I have several lists of various entities and I would like to select a set of Game entities off of these lists essentially setting up a SQL WHERE IN clause for them. 我的问题是我有多个不同实体的列表,我想从这些列表中选择一组Game实体,实际上是为它们设置了SQL WHERE IN子句。 The issue is that the lists of entities are being compared to the game entity's related entities which have a many to many relationship. 问题是实体列表正在与具有多对多关系的游戏实体的相关实体进行比较。 I have done a lot of research and tried a bunch of solutions to solve this but just cannot get it quite right, I would really appreciate some help from the stackoverflow community. 我已经做了很多研究,并尝试了很多解决方案来解决这个问题,但只是做得还不够,我真的很感谢stackoverflow社区的一些帮助。

Thanks in advance. 提前致谢。

Edit: 编辑:

I have tried doing this instead of the unions: 我尝试这样做,而不是工会:

     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;

With both the unions and this I recieve the following error message: 通过这两个联合,我收到以下错误消息:

base {System.SystemException} = {"Unable to create a constant value of type 'UltimateGameDB.Domain.Entities.Developer'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."} base {System.SystemException} = {“无法创建类型为'UltimateGameDB.Domain.Entities.Developer'的常量值。在此上下文中仅支持基本类型(例如Int32,String和Guid')。

Does anyone have any idea how to go about doing this without 有谁知道如何去做,而没有

My current code: 我当前的代码:

  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;
  }

You can't pass local entities - they won't translate to sql, in your case relatedDevelopers. 您不能传递本地实体-在您的情况下,它们将不会转换为sql,这是relatedDevelopers。 There's not a way for Linq to Entities to translate relatedDevelopers.Contains to a Sql IN . Linq to Entities没有办法转换relatedDevelopers.Contains 。包含Sql IN

You can either cast the list of games and do the call in memory so that it's not having to be translated into sql - this is easier, but if your database is huge, it could be bad to load it all, just add ToList() at the end of ugdb.Games 您可以强制转换游戏列表并在内存中进行调用,这样就不必将其转换为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;

Alternatively, you can create a list of Id's and pass that, as that's a primitive type that SQL can recognize: 另外,您可以创建一个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;

The pattern is normally to use a nested Any , or an Any with a Contains 该模式通常使用嵌套的Any或带有ContainsAny

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM