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方法订阅该消息并处理主币种变化后的预算更新。处理逻辑包括获取用户的所有预算、查询新旧币种及其汇率、将预算金额从旧币种转换为新币种,并最终更新预算数据。

相关推荐
one9962 小时前
C# 特性(Attributes)详解
c#·.net
快乐就好ya5 小时前
基于docker微服务日志ELK+Kafka搭建
spring boot·elk·spring cloud·docker·微服务·kafka
Icoolkj6 小时前
微服务学习-快速搭建
学习·微服务·架构
三天不学习6 小时前
.Net Core微服务入门系列(一)——项目搭建
微服务·架构·.netcore
小码编匠6 小时前
WinForm 轻松实现控件的焦点获取与失去
后端·c#·.net
三天不学习6 小时前
.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)
微服务·.netcore·consul
xiaolin03337 小时前
RabbitMQ确保消息可靠性
微服务·rabbitmq·springcloud·可靠性
聿琴惜荭顏丶9 小时前
.NET MAUI进行UDP通信
网络协议·udp·.net