FreeSql配合仓储实现软删除

该篇内容由个人博客点击跳转同步更新!转载请注明出处!

前段时间使用FreeSql作为ORM,写了一个简单的CMS,在这里总结一下其中的使用心得。

仓储配合全局过滤器

1. 统一的删除标志

如:数据库字段 bool IsDeleted,代表删除标志。

需要配合仓储可实现,统一的删除标志,不需要加where(r=>r.deleted==false),取数据时,自动过滤数据。

接口 ISoftDeleteAduitEntity.cs

    public interface ISoftDeleteAduitEntity
    {
        bool IsDeleted { get; set; }
        long? DeleteUserId { get; set; }
        DateTime? DeleteTime { get; set; }
    }

ConfigureServices通过配置服务,增加全局过滤器,第二个参数,可指定仓储所在的程序集(一个dll,一个项目就是一个程序集(一般一个解决方案下有多个项目,如果仓储写在多个地方,我们可以,把要扫描的程序集写在第二个参数上。))

services.AddFreeRepository(filter =>
{
    filter.Apply<ISoftDeleteAduitEntity>("SoftDelete", a => a.IsDeleted == false);
}, GetType().Assembly, typeof(AuditBaseRepository<>).Assembly);

GetType().Assembly 当前项目所在程序集。
typeof(AuditBaseRepository<>).Assembly,为AuditBaseRepository所在程序集,(LinCms.Zero.dll)

2.统一的删除时间,删除人

上文,关于配置删除标志,我们注入其提供好的仓储,会过滤掉isdeleted属性为true的值。

  public class UserService : IUserSevice
    {
        private readonly BaseRepository<LinUser> _userRepository;
        public UserService(BaseRepository<LinUser> userRepository)
        {
            _userRepository = userRepository;
        }

        public List<LinUser> GetUserList()
        {
            List<LinUser> users = _userRepository.Select.ToList();
            return users;
        }
}

那么,我们删除一个用户时,怎么增加删除时间,删除人呢。

public void Delete(int id)
{
    _userRepository.Delete(r => r.Id == id);
}

这样能删除,但删除人,删除时间并没有加上去。

这里我们注入AuditBaseRepository,重写父类Delete方法。

private readonly AuditBaseRepository<LinUser> _userRepository;
public UserService(AuditBaseRepository<LinUser> userRepository)
{
    _userRepository = userRepository;
}

public void Delete(int id)
{
    _userRepository.Delete(r => r.Id == id);
}

由于父类并非Virtual类型,这里通过new关键字重写 int Delete(Expression<Func<T, bool>> predicate)方法

public new int Delete(Expression<Func<T, bool>> predicate)
{
    if (typeof(ISoftDeleteAduitEntity).IsAssignableFrom(typeof(T)))
    {
        List<T> items = Orm.Select<T>().Where(predicate).ToList();
        return Orm.Update<T>(items)
            .Set(a => (a as ISoftDeleteAduitEntity).IsDeleted, true)
            .Set(a => (a as ISoftDeleteAduitEntity).DeleteUserId, _currentUser.Id)
            .Set(a => (a as ISoftDeleteAduitEntity).DeleteTime, DateTime.Now)
            .ExecuteAffrows();
    }

    return base.Delete(predicate);
}

全部重写删除操作,请参考https://github.com/luoyunchong/lin-cms-dotnetcore/blob/master/src/LinCms.Zero/Repositories/AuditBaseRepository.cs
这样固然能实现,但好像包含大量as,IsAssignableFrom(判断T是否继承了ISoftDeleteAduitEntity).

posted @   、天上月  阅读(1349)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示