首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >"follow“功能的业务逻辑。并发中的问题

"follow“功能的业务逻辑。并发中的问题
EN

Stack Overflow用户
提问于 2018-10-18 18:54:37
回答 1查看 135关注 0票数 0

我使用asp.net核心和实体框架。我有一个任务,需要创建一个“关注”按钮。目前,我的模型是这样的:

代码语言:javascript
运行
复制
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; }
}

我有一个跟随和取消跟随的函数,它们看起来像这样:

代码语言:javascript
运行
复制
    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()

此函数用于更新用户计数器:

代码语言:javascript
运行
复制
  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“的信息。但我希望听到这项任务的完美解决方案。

EN

回答 1

Stack Overflow用户

发布于 2018-10-18 22:40:58

考虑到这一点,我认为最好的解决方法是改变模型。你需要捕获追随者&追随者。

创建一个多对多表来存储follower/follower。

代码语言:javascript
运行
复制
CREATE TABLE followingTable 
(
FollowedUser Varchar(255), FollowingUser Varchar(255)
)

然后,您的跟随按钮将插入到此表中(如果还没有)

然后,不是递增/递减以下/关注者计数,而是根据多对多表计算值。

例如:

代码语言:javascript
运行
复制
UPDATE U

SET FollowerCount = Count(FollowingUser)
FROM
User u
join followingTable ft
on u.UserId = Ft.FollowedUser

这种方法的美妙之处在于,如果用户多次点击按钮,则不会给出错误的值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52872405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档