在实体框架中,我可以创建一个计算列来计算每一行的所有值吗?

use*_*050 6 c# calculated-columns entity-framework-core

我使用实体框架在表中有 3 个主要列(Points、TotalPoints、DateCreated)。

场景- 想象一下“Fun Arcade”,您可以通过玩游戏赚取代币,然后可以将这些代币兑换成礼物。因此,当您使用该应用程序时,您的“积分”计数或代币计数将会上下波动。

我想要什么- 我想看看实体框架是否可以计算“TotalPoints”列,这样我就不必每次将新的“Point”实体添加到表中时都执行此操作。

我知道我可以创建一个计算列值来计算同一行中的值(例如名字 col + 姓氏 col => 全名列)但我想总结该用户的“点”列中的所有值,以便插入的最后一行(基于 DateCreated 列)具有该用户的所有分数的总和。

前任。点实体

点数 1,总点数 1,创建日期

点数 3,总点数 4,创建日期

积分 2,总积分 6,创建日期

点数 -1,总点数 5,创建日期

积分 2,总积分 7,创建日期

仅供参考- 如果用户用积分交换礼物,我也可以删除积分,如上所示。

问题- 这是否可以通过 Fluent API 和 EF Core 实现,还是每次插入新的点条目时都必须手动计算?

编辑-我可以手动完成,而且似乎工作正常。但到目前为止我只有几行,所以不确定每个用户几千行的性能?

这是我所做的。

当插入新的“点”实体时,我可以像这样计算用户“点”的总和。

var totalPoints = userFromRepo.UserPoints.Sum(p => p.Points);
var point = new UserPoint() { Points = 1, TotalPoints = totalPoints+1, UserId = userFromRepo.Id, DateCreated = DateTime.UtcNow, UserPointType = UserPointType.Tip };
_unitOfWork.Repository<UserPoint>().Add(point);
Run Code Online (Sandbox Code Playgroud)

当我在登录时获取用户数据(包括点)时,我会根据插入的最后一个“点”进行获取。这节省了用户每次登录时执行某种类型的 .SUM() 或计算的时间。

前任。获取用户登录时的总积分

user.UserPoints.OrderByDescending(p => p.CreatedDate).LastOrDefault().TotalPoints)
Run Code Online (Sandbox Code Playgroud)

Cai*_*ard 1

不太清楚为什么要让数据库进行运行总和或存储它,因为如果您有其他一些需要的信息(例如“我们获得积分的日期”),则每次显示数据时都可以轻松计算它..除非您有一些只显示一段时间后的数据的用例。

对于简单的用例,显示所有数据:

var ps = context.Points.Where(p => p.UserId == blah).OrderBy(...)
var sum = 0;
foreach(var p in ps)
  Console.WriteLine($"{p.Points} {sum+=p.Points}");
Run Code Online (Sandbox Code Playgroud)

对于部分用例,显示日期 X 之后的一些数据以及播种滚动总和之前的点:

var ps = context.Points.Where(p => p.UserId == blah && p.SomeDate >= blah2).OrderBy(...)
var sum = context.Points.Where(p => p.UserId == blah && p.SomeDate < blah2).Sum(p => p.Points);

foreach(var p in ps)
  Console.WriteLine($"{p.Points} {sum+=p.Points}");
Run Code Online (Sandbox Code Playgroud)

如果你想使用视图,也许:

CREATE VIEW PointsWithSum AS
  SELECT UserId, Points, SUM(Points) OVER(PARTITION BY UserId ORDER BY SomeDate)
Run Code Online (Sandbox Code Playgroud)

搭建它,您将获得一个只读数据库集/实体,但您可以通过向其添加导航属性将其连接到其他实体,以便您可以像这样进行查询

context.PointsWithSum.Include(pws => pws.User)
  .Where(pws => pws.UserId == 123)
Run Code Online (Sandbox Code Playgroud)

或者类似..

笔记; 代码示例基于假设您有一个表 Points(整数),其中包含 UserId、Points 和 SomeDate 列,该表 EF 映射到名为 Point 的实体,该实体具有 User、Points 和 SomeDate 属性