FreeSql 过滤器使用介绍

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

1|0过滤器

目前过滤器依附在仓储层实现,每个仓储实例都有 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); }

2|0临时禁用

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

3|0如何使用仓储

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 注入,使用方法继续往下看【全局过滤器】;

4|0过滤与验证

假设我们有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);
  • 在查询/修改/删除时附加此条件,从而达到不会修改其他用户的数据;
  • 在添加时,使用表达式验证数据的合法性,若不合法则抛出异常;

5|0全局过滤器

全局过滤器,可帮助实现“软删除”、“租户”等设计,目前使用 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" \r\nFROM "Song" a \r\nWHERE (a."Title" = strftime('%Y-%m-%d %H:%M.%f',datetime(current_timestamp,'localtime')) || 21)"

repos2.Select.ToSql()

"SELECT a."Id" \r\nFROM "xxxx" a"

第二次请求:

repos1.Select.ToSql()

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

repos2.Select.ToSql()

"SELECT a."Id" \r\nFROM "xxxx" a"

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

repos1.Select.ToSql()

"SELECT a."Id", a."Title" \r\nFROM "Song" a"

测试总结:

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

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

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

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

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


__EOF__

本文作者FreeSql & CSRedis
本文链接https://www.cnblogs.com/kellynic/p/10519398.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   nicye  阅读(1940)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示