【问题标题】:How to select a entry in Database using multiple conditions?如何使用多个条件在数据库中选择一个条目?
【发布时间】:2019-01-30 18:59:09
【问题描述】:

我正在做一个有趣的项目,我正在保存用户当前的 GuildId、UserId、他们的等级和当前的 Exp。它可以部分工作,但它似乎只抓住了一个条件的第一个结果。

我尝试了多种从数据库中选择项目的不同方法,但由于这是一种爱好,我觉得我遗漏了一些非常明显的东西。我已经记录了我获取 UserId 和 GuildId 的方式,它们返回了正确的值。

如果新条目不存在,它当前会添加一个新条目,并且会正确更新 Xp,但仅限于一个条目。它似乎忽略了 GuildId,只找到与 UserId 匹配的第一个条目并将其保存在那里。

    public static async Task SaveExp(ulong guildId, ulong userId, int level, uint xp, DateTime cooldown)
    {
        using (var dbContext = new DatabaseHandler())
        {
            if (dbContext.Exps.Any(x => x.GuildId == guildId && x.UserId == userId))
            {
                var current = dbContext.Exps.FirstOrDefault(x => x.GuildId == guildId && x.UserId == userId);
                if (current != null)
                {
                    current.Xp += xp;
                    current.Level += level;
                    dbContext.Exps.Update(current);
                }
            }
            else
            {
                dbContext.Exps.Add(new Exp
                {
                    GuildId = guildId,
                    UserId = userId,
                    Level = level,
                    Xp = xp,
                    Cooldown = cooldown
                });
            }
            await dbContext.SaveChangesAsync();
        }
    }

我希望它将 Xp 保存到同时满足 GuildId 和 UserId 条件的条目中。

【问题讨论】:

  • “它似乎忽略了 GuildId,只找到匹配 UserId 的第一个条目” - 这就是 FirstOrDefault() 所做的。将多个匹配项收集到 List<Exps>
  • 这就是答案,谢谢。我能够将它放入一个列表并从中提取正确的结果!

标签: entity-framework c#-4.0


【解决方案1】:

您可以像这样稍微重构代码以提高效率。您的代码确实执行您所描述的操作。如果您应该只返回一个/null 结果,那么您应该使用SingleOrDefault/SingleOrDefaultAsync,这样可以确保更多结果会导致InvalidOperationException

public static async Task SaveExp(ulong guildId, ulong userId, int level, uint xp, DateTime cooldown)
{
    using (var dbContext = new DatabaseHandler())
    {
        var current = await dbContext.Exps.FirstOrDefaultAsync(x => x.GuildId == guildId && x.UserId == userId);
        if (current != null)
        {
            current.Xp += xp;
            current.Level += level;
            // you should not need this next line in EF6
            // the entity is already attached as you just retrieved it and should be tracked
            dbContext.Exps.Update(current);
        }
        else
        {
            dbContext.Exps.Add(new Exp
            {
                GuildId = guildId,
                UserId = userId,
                Level = level,
                Xp = xp,
                Cooldown = cooldown
            });
        }
        await dbContext.SaveChangesAsync();
    }
}

【讨论】:

  • 我要补充一点,如果 OP 试图将 Xps 添加到所有匹配的项目中,您可能会将它们抓取到一个列表中,然后循环或使用 matches.Foreach(x => x.Xp = xp); 或类似的。
  • @Dnovax - 如果您需要更多帮助,则需要生成 minimal reproducible example。创建一个可以重现问题的独立方法(或一组方法)。
猜你喜欢
  • 2011-03-20
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 2021-10-31
  • 2016-04-06
  • 2021-04-08
  • 1970-01-01
  • 2020-08-11
相关资源
最近更新 更多