Бизнес логика для функциональности «следуй».Проблема в параллелизме - PullRequest
0 голосов
/ 18 октября 2018

Я использую ядро ​​и сущность 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».Но я хотел бы услышать идеальное решение для этой задачи.

1 Ответ

0 голосов
/ 18 октября 2018

глядя на это - я думаю, что лучший способ обойти это изменить модель.Вам нужно захватить Подписчиков и Подписчиков.

Создать таблицу «многие ко многим» для хранения подписчиков / подписчиков.

CREATE TABLE followingTable 
(
FollowedUser Varchar(255), FollowingUser Varchar(255)
)

Затем кнопка «Следовать» вставляет в эту таблицу (если ее там нет)уже)

Тогда вместо того, чтобы увеличивать / уменьшать следующее число / число последователей, Вы рассчитываете значение на основе таблицы Many-to_many.

EG:

UPDATE U

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

Красотаэтот подход заключается в том, что если пользователь нажимает кнопку несколько раз, он не будет давать ложное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...