Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将嵌套的foreach写入LINQ以聚合两个单独的值_C#_Sql_.net_Linq_Entity Framework - Fatal编程技术网

C# 将嵌套的foreach写入LINQ以聚合两个单独的值

C# 将嵌套的foreach写入LINQ以聚合两个单独的值,c#,sql,.net,linq,entity-framework,C#,Sql,.net,Linq,Entity Framework,我正在尝试合计一个用户在一次挑战中可以在游戏中获得的点数和硬币总数。玩家在挑战中可以获得硬币和点数的等级如下: foreach (var challenge in userChallenges) { var coins = 0; var points = 0; coins += challenge.CoinsWhenCompleted; points += challenge.Poin

我正在尝试合计一个用户在一次挑战中可以在游戏中获得的点数和硬币总数。玩家在挑战中可以获得硬币和点数的等级如下:

foreach (var challenge in userChallenges)
        {
            var coins = 0;
            var points = 0;
            coins += challenge.CoinsWhenCompleted;
            points += challenge.PointsWhenCompleted;
            var steps = await db.Steps.Where(s => s.ChallengeId == challenge.ChallengeId).ToListAsync().ConfigureAwait(false);
            foreach (var step in steps)
            {
                coins += step.CoinsWhenCompleted;
                points += step.PointsWhenCompleted;
                var blocks = await db.StepBlocks.Where(b => b.StepId == step.StepId).ToListAsync().ConfigureAwait(false);
                foreach (var block in blocks)
                {
                    coins += block.CoinsWhenCompleted;
                    points += block.PointsWhenCompleted;
                }
            }
            challenge.TotalPossibleCoins = coins;
            challenge.TotalPossiblePoints = points;
        }
  • 挑战
    • 台阶
      • 踏板
一个挑战可以有几个步骤,一个步骤可以有几个步骤块

我把它写成了一个嵌套的foreach,但这会导致对数据库的大量查询,我想知道这是否可以通过在数据库上聚合的LINQ查询来解决,该查询只返回一个具有两个值的对象,一个值表示总可实现点,一个值表示总可实现硬币

代码如下:

foreach (var challenge in userChallenges)
        {
            var coins = 0;
            var points = 0;
            coins += challenge.CoinsWhenCompleted;
            points += challenge.PointsWhenCompleted;
            var steps = await db.Steps.Where(s => s.ChallengeId == challenge.ChallengeId).ToListAsync().ConfigureAwait(false);
            foreach (var step in steps)
            {
                coins += step.CoinsWhenCompleted;
                points += step.PointsWhenCompleted;
                var blocks = await db.StepBlocks.Where(b => b.StepId == step.StepId).ToListAsync().ConfigureAwait(false);
                foreach (var block in blocks)
                {
                    coins += block.CoinsWhenCompleted;
                    points += block.PointsWhenCompleted;
                }
            }
            challenge.TotalPossibleCoins = coins;
            challenge.TotalPossiblePoints = points;
        }
CoinsWhenCompleted
Points WhenCompleted
是特定挑战、步骤或步骤块的最大分数

我试着四处看看,但找不到何时有几个值需要聚合


感谢您的帮助,谢谢

你的主要问题是你有两个问题

您可以将其重写为以下内容:

var challengeIDs = userChallenges.Select(c => c.ChallengeId).Distinct();
var steps = await db.Steps.Where(s => challengeIDs.Contains(s.ChallengeId))
    .ToListAsync()
    .ConfigureAwait(false);

var stepIDs = steps.Select(s => s.StepId).Distinct();
var blocks = await db.StepBlocks.Where(b => stepIDs.Contains(b.StepId))
    .ToListAsync()
    .ConfigureAwait(false);

foreach (var challenge in userChallenges)
{
    challenge.TotalPossibleCoins = challenge.CoinsWhenCompleted;
    challenge.TotalPossiblePoints = challenge.PointsWhenCompleted;
    var challengeSteps = steps.Where(s => s.ChallengeId == challenge.ChallengeId).ToList();
    var stepBlocks = stepBlocks.Where(b => challengeSteps
        .Any(c => c.StepId == b.StepId))
        .ToList();

    challenge.TotalPossibleCoins += challengeSteps.Sum(c => c.CoinsWhenCompleted);
    challenge.TotalPossiblePoints += challengeSteps.Sum(c => c.PointsWhenCompleted);

    challenge.TotalPossibleCoins += stepBlocks.Sum(c => c.CoinsWhenCompleted);
    challenge.TotalPossiblePoints += stepBlocks.Sum(c => c.PointsWhenCompleted);
}
说明:

这个问题

var steps = await db.Steps.Where(s => s.ChallengeId == challenge.ChallengeId).ToListAsync().ConfigureAwait(false);
这个问题呢

var blocks = await db.StepBlocks.Where(b => b.StepId == step.StepId).ToListAsync().ConfigureAwait(false);
正在为循环的每个迭代执行

为了防止出现这种情况,我们可以简单地执行上述两个查询,但是在
foreach
循环之前执行以下操作:

var challengeIDs = userChallenges.Select(c => c.ChallengeId).Distinct();
var steps = await db.Steps.Where(s => challengeIDs.Contains(s.ChallengeId))
    .ToListAsync()
    .ConfigureAwait(false);

var stepIDs = steps.Select(s => s.StepId).Distinct();
var blocks = await db.StepBlocks.Where(b => stepIDs.Contains(b.StepId))
    .ToListAsync()
    .ConfigureAwait(false);
这意味着无论我们有多少步骤或用户挑战,我们只做了两次查询


此外,我们可以通过在Linq中简单地使用
Sum
,重构您的
foreach
语句,以获得每个子集合的汇总总数。

@DarrenDavies hahahaha WB noob,恭喜30k;)