diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 1a07ba3e7..e225edf8d 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -577,9 +577,9 @@ static void Main(string[] args) //.UseConnectionString(FreeSql.DataType.Firebird, @"database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=5") //.UseQuoteSqlName(false) - .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=3;AllowLoadLocalInfile=true") + //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=3;AllowLoadLocalInfile=true") - //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") + .UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") //.UseAdoConnectionPool(false) //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=127.0.0.1;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") ////.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=127.0.0.1;Port=5432;Username=postgres;Password=123456;Database=toc;Pooling=true;Maximum Pool Size=2") @@ -620,6 +620,51 @@ static void Main(string[] args) #endregion + var usergroupRepository = fsql.GetAggregateRootRepository(); + usergroupRepository.Delete(a => true); + usergroupRepository.Insert(new[]{ + new UserGroup + { + CreateTime = DateTime.Now, + GroupName = "group1", + UpdateTime = DateTime.Now, + Sort = 1, + User1s = new List + { + new User1 { Nickname = "nickname11", Username = "username11", Description = "desc11" }, + new User1 { Nickname = "nickname12", Username = "username12", Description = "desc12" }, + new User1 { Nickname = "nickname13", Username = "username13", Description = "desc13" }, + } + }, + new UserGroup + { + CreateTime = DateTime.Now, + GroupName = "group2", + UpdateTime = DateTime.Now, + Sort = 2, + User1s = new List + { + new User1 { Nickname = "nickname21", Username = "username21", Description = "desc21" }, + new User1 { Nickname = "nickname22", Username = "username22", Description = "desc22" }, + new User1 { Nickname = "nickname23", Username = "username23", Description = "desc23" }, + } + }, + }); + var ugroupFirst = usergroupRepository.Select.First(); + ugroupFirst.Sort++; + usergroupRepository.Update(ugroupFirst); + var userRepository = fsql.GetAggregateRootRepository(); + + var testsublist1 = fsql.Select() + .First(a => new + { + a.Id, + list = userRepository.Select.Where(b => b.GroupId == a.Id).ToList(), + list2 = userRepository.Select.Where(b => b.GroupId == a.Id).ToList(b => b.Nickname), + }); + + + FreeSql.Internal.Utils.TypeHandlers.TryAdd(typeof(DateTimeOffset), new DateTimeOffsetTypeHandler()); fsql.Insert(new Account { Name = DateTime.Now.ToString(), Join = DateTimeOffset.Now }).ExecuteAffrows(); @@ -1297,48 +1342,6 @@ static void Main(string[] args) - var usergroupRepository = fsql.GetAggregateRootRepository(); - usergroupRepository.Delete(a => true); - usergroupRepository.Insert(new[]{ - new UserGroup - { - CreateTime = DateTime.Now, - GroupName = "group1", - UpdateTime = DateTime.Now, - Sort = 1, - User1s = new List - { - new User1 { Nickname = "nickname11", Username = "username11", Description = "desc11" }, - new User1 { Nickname = "nickname12", Username = "username12", Description = "desc12" }, - new User1 { Nickname = "nickname13", Username = "username13", Description = "desc13" }, - } - }, - new UserGroup - { - CreateTime = DateTime.Now, - GroupName = "group2", - UpdateTime = DateTime.Now, - Sort = 2, - User1s = new List - { - new User1 { Nickname = "nickname21", Username = "username21", Description = "desc21" }, - new User1 { Nickname = "nickname22", Username = "username22", Description = "desc22" }, - new User1 { Nickname = "nickname23", Username = "username23", Description = "desc23" }, - } - }, - }); - var ugroupFirst = usergroupRepository.Select.First(); - ugroupFirst.Sort++; - usergroupRepository.Update(ugroupFirst); - var userRepository = fsql.GetAggregateRootRepository(); - - var testsublist1 = fsql.Select() - .First(a => new - { - a.Id, - list = userRepository.Select.Where(b => b.GroupId == a.Id).ToList(), - list2 = userRepository.Select.Where(b => b.GroupId == a.Id).ToList(b => b.Nickname), - }); //fsql.CodeFirst.GetTableByEntity(typeof(User1)).Columns.Values.ToList().ForEach(col => //{ diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepository.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepository.cs index e277f7169..207bb3d9c 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepository.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepository.cs @@ -56,6 +56,7 @@ public DbContextOptions DbContextOptions _repository.DbContextOptions.EnableCascadeSave = false; } } + public RepositoryDataFilter DataFilter => _repository.DataFilter; public void AsType(Type entityType) => _repository.AsType(entityType); Func _asTableRule; public void AsTable(Func rule) @@ -130,6 +131,7 @@ IBaseRepository GetChildRepository(Type type) repo.UnitOfWork = UnitOfWork; repo.DbContextOptions = DbContextOptions; repo.DbContextOptions.EnableCascadeSave = false; + (repo as BaseRepository).DataFilter = DataFilter; repo.AsTable(_asTableRule); return repo; } diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs index 3b8ead772..06eb16baa 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositoryAsync.cs @@ -210,6 +210,7 @@ async Task DeleteWithinBoundaryAsync(IEnumerable entitys, List= 0; a--) { + if (tracking.DeleteLog[a].Item2.Any() == false) continue; var delete = Orm.Delete().AsType(tracking.DeleteLog[a].Item1); if (_asTableRule != null) delete.AsTable(old => _asTableRule(tracking.DeleteLog[a].Item1, old)); affrows += await delete.WhereDynamic(tracking.DeleteLog[a].Item2).ExecuteAffrowsAsync(cancellationToken); @@ -240,6 +241,7 @@ async Task SaveTrackingChangeAsync(AggregateRootTrackingChangeInfo tracking for (var a = tracking.DeleteLog.Count - 1; a >= 0; a--) { + if (tracking.DeleteLog[a].Item2.Any() == false) continue; var delete = Orm.Delete().AsType(tracking.DeleteLog[a].Item1); if (_asTableRule != null) delete.AsTable(old => _asTableRule(tracking.DeleteLog[a].Item1, old)); affrows += await delete.WhereDynamic(tracking.DeleteLog[a].Item2).ExecuteAffrowsAsync(cancellationToken); diff --git a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs index cc511cf73..5e0306e37 100644 --- a/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs +++ b/Extensions/FreeSql.Extensions.AggregateRoot/AggregateRootRepository/AggregateRootRepositorySync.cs @@ -262,6 +262,7 @@ int DeleteWithinBoundary(IEnumerable entitys, List deletedOutpu var affrows = 0; for (var a = tracking.DeleteLog.Count - 1; a >= 0; a--) { + if (tracking.DeleteLog[a].Item2.Any() == false) continue; var delete = Orm.Delete().AsType(tracking.DeleteLog[a].Item1); if (_asTableRule != null) delete.AsTable(old => _asTableRule(tracking.DeleteLog[a].Item1, old)); affrows += delete.WhereDynamic(tracking.DeleteLog[a].Item2).ExecuteAffrows(); @@ -290,7 +291,8 @@ int SaveTrackingChange(AggregateRootTrackingChangeInfo tracking) } for (var a = tracking.DeleteLog.Count - 1; a >= 0; a--) - { + { + if (tracking.DeleteLog[a].Item2.Any() == false) continue; var delete = Orm.Delete().AsType(tracking.DeleteLog[a].Item1); if (_asTableRule != null) delete.AsTable(old => _asTableRule(tracking.DeleteLog[a].Item1, old)); affrows += delete.WhereDynamic(tracking.DeleteLog[a].Item2).ExecuteAffrows(); diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index d108e7ee4..510bb4c0a 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -487,6 +487,32 @@ + + + 开启过滤器,若使用 using 则使用完后,恢复为原有状态 + + 过滤器名称 + + + + + 开启所有过滤器,若使用 using 则使用完后,恢复为原有状态 + + + + + + 禁用过滤器,若使用 using 则使用完后,恢复为原有状态 + + + + + + + 禁用所有过滤器,若使用 using 则使用完后,恢复为原有状态 + + + 动态Type,在使用 Repository<object> 后使用本方法,指定实体类型 @@ -511,6 +537,11 @@ 设置 DbContext 选项 + + + GlobalFilter 禁用/启用控制 + + 清空状态数据 diff --git a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs index ddec49251..01309b80d 100644 --- a/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs +++ b/FreeSql.DbContext/Repository/ContextSet/RepositoryDbSet.cs @@ -32,6 +32,8 @@ protected override ISelect OrmSelect(object dywhere) { var select = base.OrmSelect(dywhere); if (_repo._asTablePriv != null) select.AsTable(_repo._asTablePriv); + var disableFilter = _repo.DataFilter._filtersByOrm.Where(a => a.Value.IsEnabled == false).Select(a => a.Key).ToArray(); + if (disableFilter.Any()) select.DisableGlobalFilter(disableFilter); return select; } internal ISelect OrmSelectInternal(object dywhere) => OrmSelect(dywhere); @@ -39,6 +41,8 @@ protected override IUpdate OrmUpdate(IEnumerable entitys) { var update = base.OrmUpdate(entitys); if (_repo._asTablePriv != null) update.AsTable(old => _repo._asTablePriv(_entityType, old)); + var disableFilter = _repo.DataFilter._filtersByOrm.Where(a => a.Value.IsEnabled == false).Select(a => a.Key).ToArray(); + if (disableFilter.Any()) update.DisableGlobalFilter(disableFilter); return update; } internal IUpdate OrmUpdateInternal(IEnumerable entitys) => OrmUpdate(entitys); @@ -46,6 +50,8 @@ protected override IDelete OrmDelete(object dywhere) { var delete = base.OrmDelete(dywhere); if (_repo._asTablePriv != null) delete.AsTable(old => _repo._asTablePriv(_entityType, old)); + var disableFilter = _repo.DataFilter._filtersByOrm.Where(a => a.Value.IsEnabled == false).Select(a => a.Key).ToArray(); + if (disableFilter.Any()) delete.DisableGlobalFilter(disableFilter); return delete; } internal IDelete OrmDeleteInternal(object dywhere) => OrmDelete(dywhere); diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs index d0ee01d5c..430e4df7c 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs @@ -22,6 +22,14 @@ public abstract partial class BaseRepository : IBaseRepository protected BaseRepository(IFreeSql fsql) { _ormScoped = DbContextScopedFreeSql.Create(fsql, () => _db, () => UnitOfWork); + fsql?.GlobalFilter?.GetAllFilters().ForEach(gf => + { + DataFilter._filtersByOrm.TryAdd(gf.Name, new RepositoryDataFilter.FilterItemByOrm + { + Filter = gf, + IsEnabled = true + }); + }); } ~BaseRepository() => this.Dispose(); @@ -55,6 +63,7 @@ public void AsTable(Func rule) _asTablePriv = rule; } public DbContextOptions DbContextOptions { get => _db.Options; set => _db.Options = value; } + public RepositoryDataFilter DataFilter { get; set; } = new RepositoryDataFilter(); internal DbContextScopedFreeSql _ormScoped; internal IFreeSql OrmOriginal => _ormScoped?._originalFsql; diff --git a/FreeSql.DbContext/Repository/Repository/DataFilter.cs b/FreeSql.DbContext/Repository/Repository/DataFilter.cs new file mode 100644 index 000000000..1cf972875 --- /dev/null +++ b/FreeSql.DbContext/Repository/Repository/DataFilter.cs @@ -0,0 +1,148 @@ +using FreeSql.Internal; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace FreeSql +{ + public class RepositoryDataFilter + { + internal class FilterItemByOrm + { + public GlobalFilter.Item Filter { get; set; } + public bool IsEnabled { get; set; } + } + + internal ConcurrentDictionary _filtersByOrm = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + + /// + /// 开启过滤器,若使用 using 则使用完后,恢复为原有状态 + /// + /// 过滤器名称 + /// + public IDisposable Disable(params string[] filterName) + { + if (filterName == null || filterName.Any() == false) return new UsingAny(() => { }); + + List restoreByOrm = new List(); + foreach (var name in filterName) + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm)) + { + if (tryfiByOrm.IsEnabled) + { + restoreByOrm.Add(name); + tryfiByOrm.IsEnabled = false; + } + } + } + return new UsingAny(() => + { + restoreByOrm.ForEach(name => + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm) && tryfiByOrm.IsEnabled == false) + tryfiByOrm.IsEnabled = true; + }); + }); + } + /// + /// 开启所有过滤器,若使用 using 则使用完后,恢复为原有状态 + /// + /// + public IDisposable DisableAll() + { + List restoreByOrm = new List(); + foreach (var val in _filtersByOrm) + { + if (val.Value.IsEnabled) + { + restoreByOrm.Add(val.Key); + val.Value.IsEnabled = false; + } + } + return new UsingAny(() => + { + restoreByOrm.ForEach(name => + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm) && tryfiByOrm.IsEnabled == false) + tryfiByOrm.IsEnabled = true; + }); + }); + } + class UsingAny : IDisposable + { + Action _ondis; + public UsingAny(Action ondis) + { + _ondis = ondis; + } + public void Dispose() + { + _ondis?.Invoke(); + } + } + + /// + /// 禁用过滤器,若使用 using 则使用完后,恢复为原有状态 + /// + /// + /// + public IDisposable Enable(params string[] filterName) + { + if (filterName == null || filterName.Any() == false) return new UsingAny(() => { }); + + List restoreByOrm = new List(); + foreach (var name in filterName) + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm)) + { + if (tryfiByOrm.IsEnabled == false) + { + restoreByOrm.Add(name); + tryfiByOrm.IsEnabled = true; + } + } + } + return new UsingAny(() => + { + restoreByOrm.ForEach(name => + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm) && tryfiByOrm.IsEnabled == true) + tryfiByOrm.IsEnabled = false; + }); + }); + } + /// + /// 禁用所有过滤器,若使用 using 则使用完后,恢复为原有状态 + /// + /// + public IDisposable EnableAll() + { + List restoreByOrm = new List(); + foreach (var val in _filtersByOrm) + { + if (val.Value.IsEnabled == false) + { + restoreByOrm.Add(val.Key); + val.Value.IsEnabled = true; + } + } + return new UsingAny(() => + { + restoreByOrm.ForEach(name => + { + if (_filtersByOrm.TryGetValue(name, out var tryfiByOrm) && tryfiByOrm.IsEnabled == true) + tryfiByOrm.IsEnabled = false; + }); + }); + } + + public bool IsEnabled(string filterName) + { + if (filterName == null) return false; + return _filtersByOrm.TryGetValue(filterName, out var tryfiByOrm) ? tryfiByOrm.IsEnabled : false; + } + } +} \ No newline at end of file diff --git a/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs b/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs index bd09bb41e..4a229d74e 100644 --- a/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs @@ -34,6 +34,10 @@ public interface IBaseRepository : IDisposable /// 设置 DbContext 选项 /// DbContextOptions DbContextOptions { get; set; } + /// + /// GlobalFilter 禁用/启用控制 + /// + RepositoryDataFilter DataFilter { get; } } public interface IBaseRepository : IBaseRepository diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index 597817637..1f960f18e 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -470,8 +470,9 @@ string LocalGetFilterSql(ColumnInfo[] cols, object[] objs) filter += $"{(colidx > 0 ? " AND " : "")}{aliasAndDot}{this.QuoteSqlName(col.Attribute.Name)} = "; if (CodeFirst.IsGenerateCommandParameterWithLambda && dbParams != null) //v3.5.100 单条支持参数化 { - AppendParamter(dbParams, null, col, col.Attribute.MapType, colval); - filter += RewriteColumn(col, QuoteWriteParamterAdapter(col.Attribute.MapType, QuoteParamterName($"exp_{dbParams.Count}"))); + var paramName = $"exp_{dbParams.Count}"; + AppendParamter(dbParams, paramName, col, col.Attribute.MapType, colval); + filter += RewriteColumn(col, QuoteWriteParamterAdapter(col.Attribute.MapType, QuoteParamterName(paramName))); } else filter += RewriteColumn(col, GetNoneParamaterSqlValue(null, null, col, col.Attribute.MapType, colval)); @@ -592,8 +593,9 @@ public string WhereItems(ColumnInfo[] primarys, string aliasAndDot, IEn filter += $"{aliasAndDot}{this.QuoteSqlName(pk.Attribute.Name)} = "; if (CodeFirst.IsGenerateCommandParameterWithLambda && dbParams != null) //v3.5.100 单条支持参数化 { - AppendParamter(dbParams, null, primarys[0], primarys[0].Attribute.MapType, pkval); - filter += RewriteColumn(pk, QuoteWriteParamterAdapter(primarys[0].Attribute.MapType, QuoteParamterName($"exp_{dbParams.Count}"))); + var paramName = $"exp_{dbParams.Count}"; + AppendParamter(dbParams, paramName, primarys[0], primarys[0].Attribute.MapType, pkval); + filter += RewriteColumn(pk, QuoteWriteParamterAdapter(primarys[0].Attribute.MapType, QuoteParamterName(paramName))); } else filter += RewriteColumn(pk, GetNoneParamaterSqlValue(null, null, pk, pk.Attribute.MapType, pkval));