> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 事务写入

> 使用 PlayFab 统计信息事务写入以原子方式更新多个玩家统计信息，并在进度更新期间保持一致性。

# 事务写入

在本教程中，我们将介绍如何对统计信息执行事务写入。根据用于存储统计信息的
流程，开发者可能会遇到导致操作重复的情况，尤其是使用 SUM 聚合时。为了解决这些复杂的场景，我们添加了事务写入功能。

我们将从一个包含许多同时进行比赛的多人游戏示例开始。
该游戏为每场比赛存储大量统计信息和其他遥测值。为了避免干扰
玩家体验，工作室决定每 10 分钟推送一次统计信息，而不是实时推送。

此方法可确保玩家在不同比赛之间切换时获得无缝体验。但是，它
带来了新的技术挑战。我们现在需要一个队列来每 10 分钟执行一次请求。但是如果
出于任何原因我们想要重放队列中的事件，会发生什么？那么我们可能会遇到挑战，
特别是当我们有使用 SUM 聚合的统计信息时，因为我们需要避免重复计数。

有了这个背景，我们将展示如何解决这个特定问题。

## 创建统计定义

我们首先创建一个统计定义，在此级别，我们不需要为事务写入添加任何特殊
配置。

```C# theme={null}
public static async Task CreateStatisticDefinitionAsync(PlayFabAuthenticationContext context, string statName)
{
    PlayFabProgressionInstanceAPI statsAPI = new PlayFabProgressionInstanceAPI(context);
    CreateStatisticDefinitionRequest statDefinitionRequest = new CreateStatisticDefinitionRequest()
    {
        Name = statName,
        AuthenticationContext = context,
        EntityType = "title_player_account",
        VersionConfiguration = new VersionConfiguration()
        {
            MaxQueryableVersions = 1,
            ResetInterval = ResetInterval.Manual,
        },
        Columns = new List<StatisticColumn>()
        {
            new StatisticColumn()
            {
                Name = "Eliminations",
                AggregationMethod = StatisticAggregationMethod.Sum,
            },
             new StatisticColumn()
            {
                Name = "Caliber",
                AggregationMethod = StatisticAggregationMethod.Min,
            }
        },
    };
    
    PlayFabResult<PlayFab.LeaderboardsModels.EmptyResponse> createStatDefResult = await statsAPI.CreateStatisticDefinitionAsync(statDefinitionRequest);
}
```

## 向统计信息添加数据

继续我们的示例，我们将向先前定义的统计信息添加数据。普通请求和此请求
之间的主要区别是特殊的 `TransactionId` 参数。此参数用作
被执行请求的标识符。每次有新请求到达时，系统会将新的
事务 ID 与已处理的标识符进行比较。如果找到匹配项，则不会执行该请求。

需要考虑的一个关键方面是，这种事务行为在
`TransactionId` 和被执行的请求之间建立了一种关系，而不是与该请求内的单个统计信息建立关系。
不存在针对每个单独统计信息的映射；映射是针对整个请求的。此外，当使用此功能
时，我们有一个不同的计量表来跟踪此类请求，在此处了解更多信息：[统计计量表](/services/playfab/pricing/meters/statistics-meters)

```C# theme={null}
public static async Task UpdateStatisticForPlayer(PlayFabAuthenticationContext context, string statName, string entityId, int eliminationScore, int caliberScore)
{
    PlayFabProgressionInstanceAPI statsAPI = new PlayFabProgressionInstanceAPI(context);
    UpdateStatisticsRequest updateStatRequest = new UpdateStatisticsRequest()
    {
        Entity = new PlayFab.LeaderboardsModels.EntityKey()
        {
            Id = entityId,
            Type = EntityType
        },
        AuthenticationContext = context,
        TransactionId = "YOUR_OWN_IDENTIFIER"
        Statistics = new List<PlayFab.LeaderboardsModels.StatisticUpdate>() 
        {
            new PlayFab.LeaderboardsModels.StatisticUpdate() 
            {
                Name = statName,
                Scores = new List<string> { eliminationScore.ToString(), caliberScore.ToString()},
            }
        }
    };

    PlayFabResult<UpdateStatisticsResponse> updateResult = await statsAPI.UpdateStatisticsAsync(updateStatRequest);
}
```

现在，让我们解释这个例子的一些关键元素：

* `Entity`：此参数对应于我们希望从中进行统计信息更新的实体。
* `TransactionId`：此参数对应于表示请求唯一标识符的字符串。
* `Statistics`：此参数对应于实体的实际统计信息集。
* `StatisticUpdate`：此参数对应于将要添加的统计信息值。
  * `Scores`：此参数对应于您可以添加到一个实体的分数列表。请记住，统计信息可以有多个列。
    您可以在此处深入了解这些概念：[统计信息的更多用法](/services/playfab/player-progression/statistics/doing-more-statistics)
  * `Name`：此参数对应于您在创建统计定义时设置的统计信息名称。

有了这些明确的概念，您现在已准备好向统计信息添加数据，并避免请求出现任何重复。

## 另请参阅

* [创建基本统计信息](/services/playfab/player-progression/statistics/create-basic-statistics)。
* [统计信息的更多用法](/services/playfab/player-progression/statistics/doing-more-statistics)。
* [季节性统计信息](/services/playfab/player-progression/statistics/seasonal-statistics)。
* [向统计信息添加上下文数据](/services/playfab/player-progression/statistics/metadata-statistics)。
* [API 参考](/services/playfab/player-progression/statistics/api-reference)。
* [限制](/services/playfab/player-progression/statistics/limits-statistics)。
* [配额](/services/playfab/player-progression/statistics/quota-statistics)
* [统计计量表](/services/playfab/pricing/meters/statistics-meters)。
