25. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--预算金额的币种转换

这篇文章的代码和22. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--切换主币种这篇文章的代码大体一样。这篇文章我们简单讲解一下。

既然收支记录都已经支持主币种转换的同时重新计算收支金额了,那预算也要支持切换主币种重新计算预算金额。我们一起来看一下。

一、实现

实现逻辑在这里我就不说了,不清楚的可以参考专栏的第22篇文章。

首先我们需要修改ConfigController控制器中的Update Action,在其中添加发布重新计算预算金额的消息,代码如下:

csharp 复制代码
/// <summary>
/// 更新用户配置
/// </summary>
/// <param name="configViewModel"></param>
/// <returns></returns>
[HttpPut]
[Route("Update")]
public ActionResult<ResponseData<bool>> Update([FromBody] ConfigViewModel configViewModel)
{
    try
    {
       	//more code ....
        //如果切换的是主币种,那么就将以前的所有金额全部转换成新的主币种的金额
        if (configViewModel.ConfigTypeEnum == ConfigTypeEnum.Currency)
        {
            //more code
            _ = _rabbitMqPublisher.Publish<MainCurrency>("UpdateBudgetAmount",
                "UpdateBudgetAmount", new MainCurrency()
                {
                    UserId = userId,
                    Currency = configViewModel.Value,
                    OldCurrency = oldValue
                });
        }

        return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));
    }
    catch (Exception ex)
    {
        return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常"));
    }
}

在代码中通过UpdateBudgetAmount路由键向RabbitMQ发送重新计算预算金额的消息。接着我们修改RabbitMQBackgroundService类中的StartAsync方法,在其中添加处理预算金额转换的代码,代码如下:

csharp 复制代码
public async System.Threading.Tasks.Task StartAsync(CancellationToken cancellationToken)
{
   	//more code ...
    //根据新的主币种更新预算金额
    await _subscriberService.SubscribeAsync<MainCurrency>("UpdateBudgetAmount", "UpdateBudgetAmount",
        async (mainCurrency) =>
        {
            //1.获取所有预算
            using var scope = _serviceProvider.CreateScope();
            var budgetServer = scope.ServiceProvider.GetRequiredService<IBudgetServer>();
            var budgets = budgetServer.Query(mainCurrency.UserId);

            //2.将所有预算的金额转换为新的主币种(预算中的币种转换为新的主币种)
            var currencyServer = scope.ServiceProvider.GetRequiredService<ICurrencyServer>();
            var exchangeRateRecordServer = scope.ServiceProvider.GetRequiredService<IExchangeRateRecordServer>();
            Currency? query = currencyServer.Query(mainCurrency.Currency);
            if (query == null)
            {
                return;
            }
            Currency? oldCurrency = currencyServer.Query(mainCurrency.OldCurrency);
            if (oldCurrency == null)
            {
                return;
            }
            //获取预算币种和主币种的汇率
            ExchangeRateRecord? exchangeRateRecord =
                exchangeRateRecordServer.Query($"{oldCurrency.Abbreviation}_{query.Abbreviation}");
            if(exchangeRateRecord == null)
            {
                return;
            }
            for (int i = 0; i < budgets.Count; i++)
            {
                var budget = budgets[i];
                budget.Amount = exchangeRateRecord.ExchangeRate * budget.Amount;
                budget.Remaining = exchangeRateRecord.ExchangeRate * budget.Remaining;
            }

            //3.更新所有预算
            budgetServer.Update(budgets);
        });
}

新增的这段代码的功能是通过订阅RabbitMQ的消息来处理主币种变化后的预算金额更新。首先,SubscribeAsync方法用于订阅"UpdateBudgetAmount"消息,并为每条消息定义一个异步处理逻辑。当消息接收到后,代码会使用依赖注入容器_serviceProvider创建一个新的服务范围scope,以确保在处理期间可以获取所需的服务实例。接下来,代码获取IBudgetServer服务来查询与mainCurrency.UserId关联的所有预算。然后,它使用ICurrencyServerIExchangeRateRecordServer来查询新的和旧的币种信息,以及这两种币种之间的汇率。如果查询失败,比如无法找到币种或汇率记录,处理过程将提前终止。接着,代码循环遍历所有预算,并使用获取到的汇率将每个预算的金额和剩余金额从旧币种转换为新币种。这是通过将原金额和剩余金额乘以汇率来实现的。最后,调用budgetServer.Update方法,将更新后的预算列表保存到数据库中。

二、总结

这篇文章的代码与第22篇文章中的代码基本相同,主要目的是在主币种切换时,支持预算金额的重新计算。首先介绍了ConfigController中的Update方法如何在用户配置更新时,通过RabbitMQ发布"UpdateBudgetAmount"消息,触发预算金额的重新计算。然后,文章讲解了在RabbitMQBackgroundService中新增的代码,如何通过SubscribeAsync方法订阅该消息并处理主币种变化后的预算更新。处理逻辑包括获取用户的所有预算、查询新旧币种及其汇率、将预算金额从旧币种转换为新币种,并最终更新预算数据。

相关推荐
追逐时光者2 小时前
精选 4 款基于 .NET 开源、功能强大的 Windows 系统优化工具
后端·.net
mudtools9 小时前
.NET驾驭Word之力:理解Word对象模型核心 (Application, Document, Range)
c#·.net
熙客16 小时前
SpringCloud概述
java·spring cloud·微服务
唐青枫17 小时前
从入门到进阶:C#.NET Stopwatch 计时与性能测量全攻略
c#·.net
私人珍藏库18 小时前
[Windows] 微软 .Net 运行库离线安装包 | Microsoft .Net Packages AIO_v09.09.25
microsoft·.net·运行库
追逐时光者1 天前
C#/.NET/.NET Core技术前沿周刊 | 第 54 期(2025年9.8-9.14)
后端·.net
追逐时光者1 天前
C#/.NET/.NET Core编程技巧练习集,配套详细的文章教程讲解!
后端·.net
阿里云云原生1 天前
HiMarket 正式开源,为企业落地开箱即用的 AI 开放平台
微服务
咕白m6251 天前
C# Excel 读取入门教程:免费实现方法
c#·.net
眠りたいです2 天前
基于脚手架微服务的视频点播系统-数据管理与网络通信部分的预备工作
c++·qt·ui·微服务·云原生·架构·媒体