From 2db7103dc2a1bbc97b88de18361381f037095514 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Tue, 6 Aug 2024 14:54:21 +0800 Subject: [PATCH] 1 --- 事务.md | 2 -- 过滤器.md | 95 ++++--------------------------------------------------- 2 files changed, 6 insertions(+), 91 deletions(-) diff --git a/事务.md b/事务.md index 1be7795..c9524dd 100644 --- a/事务.md +++ b/事务.md @@ -1,5 +1,3 @@ -# 事务Transaction - > dotnet add package FreeSql.DbContext ## 1、常规事务 diff --git a/过滤器.md b/过滤器.md index ea6118f..dd6f78a 100644 --- a/过滤器.md +++ b/过滤器.md @@ -1,7 +1,7 @@ -FreeSql 基础层实现了 Select/Update/Delete 可设置的全局过滤器功能。 +IFreeSql 基础层实现了 Select/Update/Delete 可设置的全局过滤器功能,这些设置将追加到执行的 SQL WHERE 语句中。 ```csharp -public static AsyncLocal TenantId { get; set; } = new AsyncLocal(); +public static AsyncLocal TenantId { get; set; } = new AsyncLocal(); fsql.GlobalFilter .Apply("test1", a => a.TenantId == TenantId.Value) @@ -10,7 +10,7 @@ fsql.GlobalFilter .ApplyOnly("test3", a => a.Name == "11") //指定类型精准设置 - .ApplyIf("test4", () => TenantId.Value != Guid.Empty, a => a.Id == TenantId.Value); + .ApplyIf("test4", () => TenantId.Value != 0, a => a.Id == TenantId.Value); //1.9.0 ApplyIf 委托的返回值(第二个参数) true 才生效 .Apply("test5", a => a.TenantId == TenantId.Value, before: true) @@ -22,7 +22,9 @@ Apply 泛型参数可以设置为任何类型,当使用 Select/Update/Delete - 匹配成功的,将附加 where 条件; - 匹配失败的,标记下次不再匹配,避免性能损耗; -如何禁用? +ApplyOnly 泛型参数指定一个类型生效。 + +## 如何禁用? ```csharp fsql.Select().ToList(); //所有生效 @@ -32,91 +34,6 @@ fsql.Select().DisableGlobalFilter().ToList(); //禁用所有 fsql.Update/Delete 方法效果同上。 -提示:全局过滤器支持子查询,请注意死循环案例 Stack overflow https://github.com/2881099/FreeSql.Wiki.VuePress/issues/10 - -# 仓储过滤器 - -> 注意:仓储过滤器属于早期功能,如果 fsql.GlobalFilter 够用的话,可以跳过以下内容。 - -FreeSql.Repository 也实现了过滤器功能,它在查询时过滤,删除/修改/插入篇还会进行验证数据,避免数据安全问题。 - -> 注意:仓储的过滤器与 IFreeSql.GlobalFilter 不是一个功能,可以同时生效。 - -> 推荐使用 IFreeSql.GlobalFilter。仓储过滤器在早期出的功能,会一直保留。 - -每个仓储实例都有 IDataFilter 属性,可利用其完成过滤器管理,它是独立的修改后不影响全局。 - -```csharp -public interface IDataFilter where TEntity : class { - IDataFilter Apply(string filterName, Expression> filterAndValidateExp); - - IDisposable Enable(params string[] filterName); - IDisposable EnableAll(); - - IDisposable Disable(params string[] filterName); - IDisposable DisableAll(); - - bool IsEnabled(string filterName); -} -``` - -## 临时禁用 - -```csharp -using (repo1.DataFilter.Disable("test")) { - //在这段中,repo1 之 test 过滤器失效 -} - -//repo1 之 test 过滤器重新生效 -``` - -## 过滤与验证 - -假设我们有User(用户)、Topic(主题)两个实体,在领域类中定义了两个仓储: - -```csharp -var userRepository = fsql.GetGuidRepository(); -var topicRepository = fsql.GetGuidRepository(); -``` - -在开发过程中,总是担心 topicRepository 的数据安全问题,即有可能查询或操作到其他用户的主题。因此我们在v0.0.7版本进行了改进,增加了 filter lambda 表达式参数。 - -```csharp -var userRepository = fsql.GetGuidRepository(a => a.Id == 1); -var topicRepository = fsql.GetGuidRepository(a => a.UserId == 1); -``` - -* 在查询/修改/删除时附加此条件,从而达到不会修改其他用户的数据; -* 在添加时,使用表达式验证数据的合法性,若不合法则抛出异常; - -## 全局 - -全局帮助实现“软删除”、“租户”等设计,目前使用 AspNetCore 注入的方式实现的全局过滤器。 - -```csharp -public void ConfigureServices(IServiceCollection services) { - - services.AddSingleton(Fsql); - services.AddFreeRepository(filter => filter - .Apply("SoftDelete", a => a.IsDeleted == false) - .Apply("Tenant", a => a.TenantId == 1) - .Apply("Song", a => a.TenantId == 1) - , - this.GetType().Assembly - ); -} -``` - -比 abpvnext 还要方便,因为 abp 的相关实体需要实现接口 ISoftDelete、ITenant; - -我们没有这个限制,只要过滤器的表达式解析成功,就算可用; - -1、设定的全局过滤,若某实体不存在表达式函数中的字段时,不会生效(如上xxxx不存在Title); - -2、使用 DataFilter.Disable("test") 可临时关闭过滤器的效果,使用 DataFilter.Enable("test") 可重新开启; - -3、仓储对象创建时,从全局过滤器copy进来,然后自己管理自己。修改后不影响其他或全局设置。 - ## 参考资料 - [《租户》](%e7%a7%9f%e6%88%b7)