zoukankan      html  css  js  c++  java
  • FreeSql 过滤器使用介绍

    FreeSql.Repository 实现了过滤器,它不仅是查询时过滤,连删除/修改/插入时都会进行验证,避免数据安全问题。

    过滤器

    目前过滤器依附在仓储层实现,每个仓储实例都有 IDataFilter 属性,可利用其完成过滤器管理,它是独立的修改后不影响全局。

    public interface IDataFilter<TEntity> where TEntity : class {
        IDataFilter<TEntity> Apply(string filterName, Expression<Func<TEntity, bool>> filterAndValidateExp);
    
        IDisposable Enable(params string[] filterName);
        IDisposable EnableAll();
    
        IDisposable Disable(params string[] filterName);
        IDisposable DisableAll();
    
        bool IsEnabled(string filterName);
    }
    

    临时禁用

    using (repos1.DataFilter.Disable("test")) {
        //在这段中,repos1 之 test 过滤器失效
    }
    
    //repos1 之 test 过滤器重新生效
    

    如何使用仓储

    dotnet add package FreeSql.Repository

    var fsql = new FreeSql.FreeSqlBuilder()
        .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|document.db;Pooling=true;Max Pool Size=10")
        .UseLogger(loggerFactory.CreateLogger<IFreeSql>())
        .UseAutoSyncStructure(true) //自动迁移实体的结构到数据库
        .Build();
    
    public class Song {
        [Column(IsIdentity = true)]
        public int Id { get; set; }
        public string Title { get; set; }
    }
    

    1、IFreeSql 的扩展方法;

    var curd1 = fsql.GetRepository<Song, int>();
    var curd2 = fsql.GetGuidRepository<Song>();
    

    2、继承现实;

    public class SongRepository : BaseRepository<Song, int> {
        public SongRepository(IFreeSql fsql) : base(fsql) {}
    
        //在这里增加 CURD 以外的方法
    }
    

    3、Autofac 注入,使用方法继续往下看【全局过滤器】;

    过滤与验证

    假设我们有User(用户)、Topic(主题)两个实体,在领域类中定义了两个仓储:

    var userRepository = fsql.GetGuidRepository<User>();
    var topicRepository = fsql.GetGuidRepository<Topic>();
    

    在开发过程中,总是担心 topicRepository 的数据安全问题,即有可能查询或操作到其他用户的主题。因此我们在v0.0.7版本进行了改进,增加了 filter lambad 表达式参数。

    var userRepository = fsql.GetGuidRepository<User>(a => a.Id == 1);
    var topicRepository = fsql.GetGuidRepository<Topic>(a => a.UserId == 1);
    
    • 在查询/修改/删除时附加此条件,从而达到不会修改其他用户的数据;
    • 在添加时,使用表达式验证数据的合法性,若不合法则抛出异常;

    全局过滤器

    全局过滤器,可帮助实现“软删除”、“租户”等设计,目前使用 Autofac 注入的方式实现的全局过滤器。

    public IServiceProvider ConfigureServices(IServiceCollection services) {
        services.AddSingleton<IFreeSql>(fsql);
        services.AddMvc();
    
        var builder = new ContainerBuilder();
    
        //示范全局过滤的仓储类注入,如果实体中不存在 Title 属性,则条件不生效
        builder.RegisterFreeRepository(filter => 
            filter.Apply<Song>("test", a => a.Title == DateTime.Now.ToString() + Thread.CurrentThread.ManagedThreadId)
        );
    
        builder.Populate(services);
        var container = builder.Build();
        return new AutofacServiceProvider(container);
    }
    
    public class xxxx {
        public int Id { get; set; }
    }
    public class Song {
        [Column(IsIdentity = true)]
        public int Id { get; set; }
        public string Title { get; set; }
    }
    //在控制器使用
    public SongsController(GuidRepository<Song> repos1, GuidRepository<xxxx> repos2) {
        //在此打断点,调试
    }
    

    第一次请求:

    repos1.Select.ToSql()

    "SELECT a."Id", a."Title" FROM "Song" a WHERE (a."Title" = strftime('%Y-%m-%d %H:%M.%f',datetime(current_timestamp,'localtime')) || 21)"

    repos2.Select.ToSql()

    "SELECT a."Id" FROM "xxxx" a"

    第二次请求:

    repos1.Select.ToSql()

    "SELECT a."Id", a."Title" FROM "Song" a WHERE (a."Title" = strftime('%Y-%m-%d %H:%M.%f',datetime(current_timestamp,'localtime')) || 4)"

    repos2.Select.ToSql()

    "SELECT a."Id" FROM "xxxx" a"

    //禁用过滤器
    repos1.DataFilter.Disable("test")

    repos1.Select.ToSql()

    "SELECT a."Id", a."Title" FROM "Song" a"

    测试总结:

    1、注入的变量值在使用时有了动态变化,每次获取时都是新的(Thread.CurrentThread.ManagedThreadId);

    2、设定的全局过滤,若某实体不存在表达式函数中的字段时,不会生效(如上xxxx不存在Title);

    3、使用 DataFilter.Disable("test") 可临时关闭过滤器的效果,使用 DataFilter.Enable("test") 可重新开启;

    4、仓储对象创建时,从全局过滤器copy进来,然后自己管理自己。修改后不影响其他或全局设置。

    github 源码: https://github.com/2881099/FreeSql

  • 相关阅读:
    LeetCode234回文链表
    LeetCode445两数相加II
    LeetCode24两两交换链表中的节点
    LeetCode19删除链表的倒数第N个节点
    LeetCode513找树左下角的值
    LeetCode637二叉树的层平均值
    LeetCode671二叉树中第二小的节点
    LeetCode337打家劫舍III
    LeetCode124二叉树中的最大路径和
    LeetCode687最长同值路径
  • 原文地址:https://www.cnblogs.com/kellynic/p/10519398.html
Copyright © 2011-2022 走看看