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的玩家一条数据。
问题根源
playerTotals在循环外初始化,每次循环都是修改同一个对象的属性,然后重复添加到列表,最终列表里的所有条目都是同一个对象的引用,且重复添加。- 外层循环遍历的是所有Players记录(包含同一玩家的多条周数据),导致同一玩家的Id被多次处理,重复添加汇总对象。
- 多次调用
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
相关产品推荐
相关产品推荐

