【问题标题】:Update an entity's property's values in the database whithin a repository query but before the query returns在存储库查询中但在查询返回之前更新数据库中实体的属性值
【发布时间】:2021-08-25 23:12:16
【问题描述】:

我知道我的标题听起来有点混乱,但这里有更好的解释:

我有一个使用 ASP.NET CORE 和 .NET 5 制作的 API,我使用存储库模式来执行我的所有数据库查询。

对于其中一个查询,我需要进行某种计算,并将该计算的结果设置为数据库中实体属性之一的值,然后才能返回整个对象,但是计算需要在查询返回之前进行,因为我需要查询也返回对象内的新值。

换句话说,这就是我目前所拥有的:

public async Task<IReadOnlyList<Place>> GetAllPlacesByCategoryWithRelatedDataAndFilters(Guid id, string city)
    {
        // I need the ratio to be calculated before I return "places"
        var places = await context.Places
            .Include(d => d.Category)
            .Where(d => d.CategoryId == id)
            .ToListAsync();

        foreach(var place in places)
        {
            // Ratio is a double
            place.Ratio = CalculateRatioByMultiplying(place.Amount1, place.Amount2);
            // Here's where I don't know how to really update the value inside of the
            // database, if I leave it like this then it will show the new value when
            // the query is performed but the value is still the default value in the
            // database

            // I've also tried this but this time nothing happens,
            // it doesn't even throw an Exception or anything and the value
            // is still the default value in the database
            var ratio = CalculateRatioByMultiplying(place.Amount1, place.Amount2);
            place.Ratio = ratio;
            await placeRepository.UpdateAsync(place);

            // Also the CalculateRatioByMultiplying is a method I've added to the
            // IPlaceRepository and so in this PlaceRepository too that just
            // multiplies arg1 with arg2 and returns a double
        }

        // Re-do the query with the new Ratio values for each of the places
        var places = await context.Places
            .Include(d => d.Category)
            .Where(d => d.CategoryId == id)
            .Where(d => d.Ratio != 0
            && d.City == city)
            .OrderByDescending(d => d.Ratio)
            .Take(10)
            .ToListAsync();

        return places;
    }

但是,我也使用中介模式从控制器中查询(我使用的是干净的架构),有时我对是否应该在“GetAllPlacesByCategoryWithRelatedDataAndFiltersQueryHandler"(调用查询的地方)或直接在存储库中。

很遗憾,我无法分享该项目或任何示例代码,因为它是一个私人项目,但我当然可以回答您的任何问题。

感谢您的帮助

【问题讨论】:

  • 我认为您应该有一个查询 (queryA),它只返回未修改的结果。然后您还需要一个实际使用该 queryA 并应用/保持更改的命令/操作 (commandA)。然后您进行第三个查询/命令 commandB,它同时使用 queryA 和 commandA 并返回一些值。见stackoverflow.com/questions/8862888/…
  • @Bangonkali 我实际上已经尝试过这样的事情,但它没有用,我试图把它放在命令中,调用多个命令(更新一个然后获取一个)但没有成功了,谢谢你的回答!

标签: c# asp.net-core asp.net-web-api entity-framework-core .net-5


【解决方案1】:

您在查询数据时尝试更新某些内容(执行命令)。不确定您是否使用 CQRS,但这仍然是关注点分离问题。

我建议您从该查询中完全删除place.Ratio 的更新。在所有可能对place.Ratio 产生影响的命令中,您可以发布/调度PlaceRatioRequiredChangedEvent 事件(对于MediatR,它是INotification)然后处理此事件/通知。

我知道这是一项艰巨的工作,但它会为以后的开发设置更好的业务流程。

【讨论】:

  • 太棒了,非常感谢,我认为它需要是一个事件,是的,我正在使用 CQRS,只有一个问题:当我添加应该更改 Ratio 值的事件时,执行我调用存储库的 UpdateAsync 方法或 CQRS 的 UpdateCommand ?
  • @SachaPerson 我会说这取决于你的个人品味:)。由于我在 CQRS、EF core 和 MediatR 中不使用 Repository,所以我会做最简单的方法:实现 INotificationHandler 并在其中注入 XXXDbContext,然后更新 place.Ratio。实现可能会因您的结构而异。但请记住,MediatR 的编写(毫无野心)是为了简化和减少我们代码中的噪音,因此无需使事情复杂化 :)
  • 谢谢!如果可行,我会尝试并让您的答案成为公认的答案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多