实体框架中的嵌套查询

问题描述 投票:0回答:5

我遇到以下异常:

不支持嵌套查询。操作1='案例' 操作2='收集'

通过此查询

var Games = context.Games.Select(a => new GameModel
{
     Members = (a.Type == 1 ? (a.UsersInGames.Where(b => b.GameID == a.ID && b.StatusID == 1).Select(c => new Member
     {
         ID = c.UserID,
         email = c.UserInfo.EmailAddress,
         screenName = c.UserInfo.ScreenName
     })) :   
    (a.Teams.Where(b => b.GameID == a.ID).SelectMany(b => b.UsersInTeams.Where(c => c.StatusID == 1)).Select(d => new Member
    {
        ID = d.UserID,
        email = d.UserInfo.EmailAddress,
        screenName = d.UserInfo.ScreenName
    )))
})

当我在选择成员时不包含条件时,查询工作正常。有没有办法可以在查询中执行条件?

c# linq entity-framework
5个回答
39
投票

您高估了 LINQ 转换为 SQL 的能力。并非所有内容都是可翻译的,并且由于 LINQ 的工作方式,因此不会出现编译器警告。

嵌套集合通常要么 a) 不受支持,要么 b) 最终导致可怕的 SELECT N+1 查询。你要求 EF 做的就是返回一个对象树。 SQL 不支持树状结果,所以你会遇到对象关系阻抗不匹配的问题,这很糟糕。

我建议您将嵌套集合数据作为第二个完全独立的查询来获取。这可以让您更好地控制并保证有效。

作为一个非必要的旁注,您可能无法说服 EF 在序列上使用 ?: 运算符。这很难翻译。想想如何将其编写为 SQL - 非常困难且复杂。


21
投票

Linq to EF 似乎不支持以下内容

context.Games.Select(g => new
{
    Field = g.IsX? queryable1 : queryable2
});

但是,您可以使用以下技巧来使其正常工作:

context.Games.Select(g => new
{
    Field = queryable1.Where(q => g.IsX)
               .Concat(queryable2.Where(q => !g.IsX))
});

3
投票

我也遇到了同样的问题。解决方案是加载两个结果并确定在查询后使用什么(我知道它有性能下降),但至少如果截止日期攻击你,你可以暂时这样做:

在 LINQ 端

  var Games = context.Games.Select(a => new GameModel
        {
            // carries type1 results
            Members = a.UsersInGames.Where(b => b.GameID == a.ID && b.StatusID == 1).Select(c => new Member
            {
                ID = c.UserID,
                email = c.UserInfo.EmailAddress,
                screenName = c.UserInfo.ScreenName
            })),

             //You need to create this temporary carrier to carry type 2 results
             MembersOfType2 = a.Teams.Where(b => b.GameID == a.ID).SelectMany(b => b.UsersInTeams.Where(c => c.StatusID == 1)).Select(d => new Member
                {
                    ID = d.UserID,
                    email = d.UserInfo.EmailAddress,
                    screenName = d.UserInfo.ScreenName
                })))
            })
        }

之后,您可以循环

Games
并为某个游戏分配
Members = MembersOfType2
if
Type == 1


3
投票

我也有这个错误。我有这样的代码:

var Games = context.Games.Select(a => new GameModel
{
    Members = (!filters.GetDatailedDataToo ? null : new List<MemberModel>())
};

null
操作中使用
? :
时会出现此错误。

这不是那种情况,写在这里,但我浪费了很多时间,我想任何人都使用这种情况,谁搜索这个错误文本..


0
投票

我们希望让客户在 2021 年添加命令,使用嵌套查询将如下所示:

     List<Client> clients = this.db.Clients.Where(c => db.Commandes.Where(cmd => cmd.Datecommande.Year == 2021).Select(cmd => cmd.ClientId).Contains(c.Id)).ToList();

这相当于:

Select * from clients where id any (select id from commandes where .... )
© www.soinside.com 2019 - 2024. All rights reserved.