【发布时间】:2018-10-18 10:54:36
【问题描述】:
我使用 asp.net 核心和实体框架。我有一项任务需要创建一个“关注”按钮。 目前,我的模型如下所示:
public class Following
{
[Key, Column(Order = 0), ForeignKey("UserId")]
public string UserId { get; set; }
[Key, Column(Order = 1), ForeignKey("FollowerId")]
public string FollowerId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public bool IsFollowing { get; set; }
}
我有一个关注和取消关注功能,它们看起来像这样:
public async Task<bool> Follow(string userId, string currentUserId)
{
var currentExist = await GetFollower(userId, currentUserId);
// insert if new
if (currentExist == null)
{
var newFollower = new Following()
{
FollowerId = currentUserId,
UserId = userId,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
IsFollowing = true
};
InsertFollower(newFollower);
// update counters
updateFollow(userId, currentUserId);
return true;
}
if (currentExist.IsFollowing)
return false;
currentExist.UpdatedAt = DateTime.UtcNow;
currentExist.IsFollowing = true;
context.Entry(currentExist);
// update counters
updateFollow(userId, currentUserId);
return true;
}
public async Task<bool> UnFollow(string userId, string currentUserId)
{
// this I get user from db
var exist = await GetFollower(userId, currentUserId);
if (exist == null || !exist.IsFollowing) return false;
exist.UpdatedAt = DateTime.UtcNow;
exist.IsFollowing = false;
context.Entry(exist).State = EntityState.Modified;
updateUnFollow(userId, currentUserId);
return true;
}
接下来,我调用 SaveChangesAsync()
此函数更新用户计数器:
private async Task updateFollow(string userId, string currentUserId)
{
await context.Database.ExecuteSqlCommandAsync("UPDATE User SET FollowerCount = FollowerCount + 1 WHERE UserId = {0}", userId);
await context.Database.ExecuteSqlCommandAsync("UPDATE User SET FollowingCount = FollowingCount + 1 WHERE UserId = {0}", currentUserId);
}
private async Task updateUnFollow(string userId, string currentUserId)
{
await context.Database.ExecuteSqlCommandAsync("UPDATE User SET FollowerCount = FollowerCount - 1 WHERE UserId = {0}", userId);
await context.Database.ExecuteSqlCommandAsync("UPDATE User SET FollowingCount = FollowingCount - 1 WHERE UserId = {0}", currentUserId);
}
问题是,如果我多次点击“关注”按钮。一次又一次地取消订阅和订阅。我会得到一个不正确的计数器值,此外有时还会出现“并发”错误。换句话说,计数器值有时低于 1,有时高于 1,很少在正确值为 1 时。 这行是从数据库中删除还是更新都没有区别。
我希望此功能看起来像 github 之类的“星形”按钮。
在互联网上,我设法找到了有关“rowversion”的信息。但我想听听这项任务的完美解决方案。
【问题讨论】:
-
我会先问自己,为什么要存储一个多余的计数值?在运行时进行计数真的是性能问题吗?
-
但我想听听这个任务的完美解决方案。这有点……宽泛。
-
@GertArnold 为什么保留它?在用户页面上显示此数据,而不是在访问用户页面时不断统计用户
-
@GertArnold 就像这里的“赞”按钮一样。我想要同样的解决方案。
-
您在查询当前计数时是否真的遇到过性能问题?数据库往往非常擅长计数。不要低估冗余带来的麻烦。
标签: asp.net sql-server asp.net-mvc entity-framework