You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Forms中SQLite玩家数据合并重复添加问题求助

Xamarin Forms SQLite玩家统计数据汇总重复添加问题

这是一款基于SQLite数据库的Xamarin Forms应用,用于记录本地台球联赛的玩家统计数据。玩家模型定义如下:

public class Players
{
    [PrimaryKey, AutoIncrement]
    public int EntryId { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
    public int GamesWon { get; set; }
    public int GamesLost { get; set; }
    public int GamesPlayed { get; set; }
    public decimal Average { get; set; }
    public int WeekNumber { get; set; }
}

每周会新增玩家数据,其中GamesPlayed和Average字段在插入前计算,其余字段来自UI输入。当前需求是从Players表中获取所有数据,将每个玩家的GamesWon、GamesLost数据汇总后添加到新列表用于展示。

现有实现代码如下:

public async Task<List<Players>> ConsolidatePlayer()
{
    Players playerTotals = new Players();
    var players = await playerService.GetAllPlayersAsync();

    if (players.Count == 0)
    {
        return null;
    }
    else
    {
        foreach (var item in players)
        {
            
            var getPlayerData = await playerService.GetAllBySingleId(item.Id);

            if (getPlayerData != null)
            {
                foreach (var single in getPlayerData)
                {
                    playerTotals.Id = single.Id;
                    playerTotals.Name = single.Name;
                    playerTotals.GamesWon += single.GamesWon;
                    playerTotals.GamesLost += single.GamesLost;
                    playerTotals.GamesPlayed = playerTotals.GamesWon + playerTotals.GamesLost;
                    playerTotals.Average = Decimal.Round((decimal)(playerTotals.GamesWon / (decimal)playerTotals.GamesPlayed) * 100, 2);
                    playerTotals.WeekNumber = single.WeekNumber;
                }
            }

            pList.Add(playerTotals);
        }

    }
    return pList;
}

存在的问题

playerTotals会被重复添加到列表中,例如Id为1的玩家被添加8次。尝试通过计数器对比getPlayerData的数量来控制添加次数后,列表中仅保留Id为2的玩家一条数据。

问题根源

  1. playerTotals在循环外初始化,每次循环都是修改同一个对象的属性,然后重复添加到列表,最终列表里的所有条目都是同一个对象的引用,且重复添加。
  2. 外层循环遍历的是所有Players记录(包含同一玩家的多条周数据),导致同一玩家的Id被多次处理,重复添加汇总对象。
  3. 多次调用GetAllBySingleId查询同一玩家数据,既浪费性能又容易引发逻辑错误。

修正方案

通过分组处理同一玩家的所有数据,为每个玩家单独创建汇总对象,避免重复引用和重复添加:

public async Task<List<Players>> ConsolidatePlayer()
{
    var allPlayers = await playerService.GetAllPlayersAsync();

    // 空数据时返回空列表,比返回null更友好
    if (!allPlayers.Any())
    {
        return new List<Players>();
    }

    // 按玩家Id分组,把同一玩家的所有周数据归为一组
    var groupedPlayers = allPlayers.GroupBy(player => player.Id);
    var consolidatedPlayers = new List<Players>();

    foreach (var playerGroup in groupedPlayers)
    {
        // 为每个玩家创建新的汇总对象,避免引用重复
        var playerTotals = new Players
        {
            Id = playerGroup.Key,
            // 取该玩家的名称(假设同一Id的Name始终一致)
            Name = playerGroup.First().Name
        };

        // 累加该玩家的所有胜负数据
        foreach (var weeklyData in playerGroup)
        {
            playerTotals.GamesWon += weeklyData.GamesWon;
            playerTotals.GamesLost += weeklyData.GamesLost;
        }

        // 计算总场次和胜率,避免除以0的情况
        playerTotals.GamesPlayed = playerTotals.GamesWon + playerTotals.GamesLost;
        if (playerTotals.GamesPlayed > 0)
        {
            playerTotals.Average = Decimal.Round(
                (decimal)(playerTotals.GamesWon / (decimal)playerTotals.GamesPlayed) * 100, 
                2
            );
        }
        else
        {
            playerTotals.Average = 0;
        }

        // 设置周数为该玩家的最新周数,可根据需求调整
        playerTotals.WeekNumber = playerGroup.Max(p => p.WeekNumber);

        // 将汇总后的玩家对象添加到列表
        consolidatedPlayers.Add(playerTotals);
    }

    return consolidatedPlayers;
}

关键改进点

  • 使用GroupBy按玩家Id分组,一次性获取所有玩家的分组数据,避免重复查询和处理同一玩家
  • 每个玩家单独创建playerTotals对象,彻底解决同一引用重复添加的问题
  • 增加了除以0的判断,防止胜率计算时出现异常
  • 返回空列表而非null,符合集合类型返回的最佳实践
  • 减少了不必要的数据库查询,提升代码性能

内容的提问来源于stack exchange,提问作者SithLord2K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:15:34