For the complete documentation index, see llms.txt. This page is also available as Markdown.

写入操作

以帖子投票、主题审核和浏览记录说明真实写入及其副作用。

数据写入既改变记录,也可能影响统计、审核状态和文件存储。Discussions 将这些规则放在业务服务中;调用者应优先使用服务动作,而不是从控制器直接修改表。

新建模型并写入投票

来源:src/Services/PostService.cs(节选;上下文见源文件)。

PostService.cs
public bool Upvote(ulong postId, byte value = 1)
{
	if(value == 0)
		value = 1;

	var userId = this.Principal.Identity.GetIdentifier<uint>();

	using(var transaction = new Transaction())
	{
		this.DataAccess.Delete<Post.PostVoting>(
			Condition.Equal(nameof(Post.PostVoting.PostId), postId) &
			Condition.Equal(nameof(Post.PostVoting.UserId), userId));

		this.DataAccess.Insert(Model.Build<Post.PostVoting>(voting =>
		{
			voting.PostId = postId;
			voting.UserId = userId;
			voting.Value = (sbyte)Math.Min(value, (sbyte)100);
			voting.Timestamp = DateTime.Now;
		}));

		//如果帖子投票统计信息更新成功
		if(this.SetPostVotes(postId))
		{
			//提交事务
			transaction.Commit();

			//返回成功
			return true;
		}
	}

	return false;
}

实际流程先删除当前用户对该帖的旧投票,再通过 Model.Build 创建新记录,最后重算正负票数。只有统计更新成功才提交事务。Value 被限制在 1 到 100,统计的是记录数而非权重总和。

删除也需要业务范围

上面的 Delete 同时指定 PostId 与 UserId:删除的是当前用户对当前帖的旧票。缺少其中一个条件都会扩大影响范围。通用 Delete API 不能替代当前身份与目标资源的授权判断。

更新主题状态

来源:src/Services/ThreadService.cs(节选;上下文见源文件)。

锁定是一个明确的业务动作,版主条件和主题编号一起控制更新。字段的意义、回复入口是否检查锁定,以及界面反馈,需要按完整调用链核对;仅设置 IsLocked 不等于所有自定义写入入口都会自动阻止回复。

新增或更新浏览记录

来源:src/Services/ThreadService.cs(节选;上下文见源文件)。

Upsert 围绕浏览记录键执行新增或更新,同时递增 ViewedCount。是否支持相应写入表达式取决于数据库驱动;不要把一种驱动的 SQL 形式推广到全部数据库。

内容文件与数据库不是同一事务

长正文可能先保存到文件,再将路径写入数据库。数据库回滚不会自动删除对象存储文件,因此相关服务使用失败补偿。生产接入还需检查异常、取消、重试和旧文件清理。详见文件系统与事务。

Discussions 没有直接调用 IDataAccess.Import 的业务流程;批量导入能力仍需独立验证站点字段、权限和重复数据策略。

最后更新于