首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# 點贊/踩邏輯:狀態機模型與資料庫設計

     編輯:程式設計疑難解答

需求:點贊 (讚/取消)、踩 (踩/取消),互斥 (贊→踩 變踩,踩→贊 變贊),顯示即時計數。

資料庫設計


CREATE TABLE PostVote (
    PostId BIGINT NOT NULL,
    UserId BIGINT NOT NULL,
    VoteType TINYINT NOT NULL, -- 1=贊, -1=踩, 0=取消(軟刪除或不存)
    CreatedAt DATETIME DEFAULT GETDATE(),
    PRIMARY KEY (PostId, UserId)
);
-- 統計視圖
CREATE VIEW PostVoteStats AS
SELECT PostId,
       SUM(CASE WHEN VoteType=1 THEN 1 ELSE 0 END) AS LikeCount,
       SUM(CASE WHEN VoteType=-1 THEN 1 ELSE 0 END) AS DislikeCount
FROM PostVote
GROUP BY PostId;

後端 API (ASP.NET Core)


[HttpPost("api/posts/{postId}/vote")]
public async Task Vote(long postId, [FromBody] VoteDto dto) {
    var userId = GetCurrentUserId();
    using var tx = await _db.Database.BeginTransactionAsync();
    var existing = await _db.PostVotes.FindAsync(postId, userId);
    int newType = dto.Type; // 1 or -1
    if (existing != null) {
        if (existing.VoteType == newType) {
            _db.PostVotes.Remove(existing); // 取消同類型
            newType = 0;
        } else {
            existing.VoteType = newType; // 切換類型
        }
    } else {
        _db.PostVotes.Add(new PostVote { PostId=postId, UserId=userId, VoteType=newType });
    }
    await _db.SaveChangesAsync();
    await tx.CommitAsync();
    var stats = await _db.PostVoteStats.FindAsync(postId);
    return Ok(new { like = stats.LikeCount, dislike = stats.DislikeCount, myVote = newType });
}

前端 Vue 3 + Axios 範例




關鍵點總結

  1. 唯一鍵 (PostId, UserId) 保證單用戶單態度,天然防重複。
  2. 事務 + 行鎖 避免併發競爭導致計數不一致。
  3. 狀態機:無 → 贊 → 無 → 踩 → 無,或 贊 ↔ 踩 直接切換。
  4. 前端樂觀 UI:先切換樣式,API 失敗再回滾。

這套「資料庫唯一約束 + 事務切換狀態 + 統計視圖」模式,支援高併發、邏輯清晰、易擴充 (如加入「愛心、笑臉、驚訝」多表情)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved