From 04107d3d24355d3592fce4f61689408bae7181eb Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Thu, 21 Nov 2019 16:42:20 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20Repository/DbContext?= =?UTF-8?q?=20SaveMany=20=E6=96=B9=E6=B3=95=E5=AE=9E=E7=8E=B0=E4=B8=80?= =?UTF-8?q?=E5=AF=B9=E5=A4=9A=EF=BC=8C=E5=AD=90=E6=95=B0=E6=8D=AE=E7=9A=84?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E4=BF=9D=E5=AD=98=EF=BC=9B=20-=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20SaveManyToMany=20=E6=96=B9=E6=B3=95=E5=90=8D?= =?UTF-8?q?=E4=B8=BA=20SaveMany=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/DbContext/DbContext.cs | 14 ++- .../DbContext/DbContextOptions.cs | 4 +- FreeSql.DbContext/DbSet/DbSetAsync.cs | 57 ++++++------ FreeSql.DbContext/DbSet/DbSetSync.cs | 91 ++++++++++++------- FreeSql.DbContext/FreeSql.DbContext.xml | 43 ++++----- .../Repository/Repository/BaseRepository.cs | 4 +- .../Repository/BaseRepositoryAsync.cs | 4 +- .../Repository/Repository/IBasicRepository.cs | 10 +- FreeSql.DbContext/readme.md | 4 +- .../RepositoryTests.cs | 6 +- .../FreeSql.Tests.DbContext/UnitTest1.cs | 4 +- FreeSql/FreeSql.xml | 3 +- FreeSql/Interface/Curd/ISelect/ISelect1.cs | 3 +- .../SelectProvider/Select0Provider.cs | 8 +- .../SelectProvider/Select1Provider.cs | 4 +- 15 files changed, 150 insertions(+), 109 deletions(-) diff --git a/FreeSql.DbContext/DbContext/DbContext.cs b/FreeSql.DbContext/DbContext/DbContext.cs index 7db324cf..9524f9b4 100644 --- a/FreeSql.DbContext/DbContext/DbContext.cs +++ b/FreeSql.DbContext/DbContext/DbContext.cs @@ -158,14 +158,18 @@ namespace FreeSql this.Set().AddOrUpdate(data); } /// - /// 保存实体的指定 ManyToMany 导航属性 + /// 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + /// 场景:在关闭级联保存功能之后,手工使用本方法 + /// 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + /// 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + /// 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 /// /// 实体对象 /// 属性名 - public void SaveManyToMany(TEntity data, string propertyName) where TEntity : class + public void SaveMany(TEntity data, string propertyName) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - this.Set().SaveManyToMany(data, propertyName); + this.Set().SaveMany(data, propertyName); } /// @@ -212,10 +216,10 @@ namespace FreeSql CheckEntityTypeOrThrow(typeof(TEntity)); return this.Set().AddOrUpdateAsync(data); } - public Task SaveManyToManyAsync(TEntity data, string propertyName) where TEntity : class + public Task SaveManyAsync(TEntity data, string propertyName) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - return this.Set().SaveManyToManyAsync(data, propertyName); + return this.Set().SaveManyAsync(data, propertyName); } #endif #endregion diff --git a/FreeSql.DbContext/DbContext/DbContextOptions.cs b/FreeSql.DbContext/DbContext/DbContextOptions.cs index 95cd5630..d8492bbe 100644 --- a/FreeSql.DbContext/DbContext/DbContextOptions.cs +++ b/FreeSql.DbContext/DbContext/DbContextOptions.cs @@ -9,9 +9,9 @@ namespace FreeSql { /// - /// 是否开启一对多,多对多联级保存功能 + /// 是否开启一对多,多对多级联保存功能 /// - /// 【一对多】模型下, 保存时可联级保存实体的属性集合。出于使用安全考虑我们没做完整对比,只实现实体属性集合的添加或更新操作,所以不会删除实体属性集合的数据。 + /// 【一对多】模型下, 保存时可级联保存实体的属性集合。出于使用安全考虑我们没做完整对比,只实现实体属性集合的添加或更新操作,所以不会删除实体属性集合的数据。 /// 完整对比的功能使用起来太危险,试想下面的场景: /// - 保存的时候,实体的属性集合是空的,如何操作?记录全部删除? /// - 保存的时候,由于数据库中记录非常之多,那么只想保存子表的部分数据,或者只需要添加,如何操作? diff --git a/FreeSql.DbContext/DbSet/DbSetAsync.cs b/FreeSql.DbContext/DbSet/DbSetAsync.cs index 0adf77f3..07123ef8 100644 --- a/FreeSql.DbContext/DbSet/DbSetAsync.cs +++ b/FreeSql.DbContext/DbSet/DbSetAsync.cs @@ -133,22 +133,44 @@ namespace FreeSql } } - async public Task SaveManyToManyAsync(TEntity item, string propertyName) + async public Task SaveManyAsync(TEntity item, string propertyName) { if (item == null) return; - if (_table.Properties.ContainsKey(propertyName) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}"); + if (string.IsNullOrEmpty(propertyName)) return; + if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}"); if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException($"{_table.Type.FullName} 类型已设置属性 {propertyName} 忽略特性"); + var tref = _table.GetTableRef(propertyName, true); - if (tref.RefType != Internal.Model.TableRefType.ManyToMany) throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 ManyToMany 特性"); - DbContextExecCommand(); + if (tref == null) return; + switch (tref.RefType) + { + case Internal.Model.TableRefType.OneToOne: + case Internal.Model.TableRefType.ManyToOne: + throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 OneToMany 或 ManyToMany 特性"); + } + + await DbContextExecCommandAsync(); var oldEnable = _db.Options.EnableAddOrUpdateNavigateList; _db.Options.EnableAddOrUpdateNavigateList = false; - await AddOrUpdateNavigateListAsync(item, false, propertyName); - _db.Options.EnableAddOrUpdateNavigateList = oldEnable; + try + { + await AddOrUpdateNavigateListAsync(item, false, propertyName); + if (tref.RefType == Internal.Model.TableRefType.OneToMany) + { + await DbContextExecCommandAsync(); + //删除没有保存的数据 + var propValEach = GetItemValue(item, prop) as IEnumerable; + await _db.Orm.Select().AsType(tref.RefEntityType).WhereDynamic(propValEach, true) + .ToDelete().ExecuteAffrowsAsync(); + } + } + finally + { + _db.Options.EnableAddOrUpdateNavigateList = oldEnable; + } } async Task AddOrUpdateNavigateListAsync(TEntity item, bool isAdd, string propertyName = null) { - Type itemType = null; Func action = async prop => { if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return; @@ -163,26 +185,7 @@ namespace FreeSql return; } - object propVal = null; - if (itemType == null) itemType = item.GetType(); - if (_table.TypeLazy != null && itemType == _table.TypeLazy) - { - var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary()).GetOrAdd(prop.Name, propName => - _table.TypeLazy.GetField($"__lazy__{propName}", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance)); - if (lazyField != null) - { - var lazyFieldValue = (bool)lazyField.GetValue(item); - if (lazyFieldValue == false) return; - } - propVal = prop.GetValue(item); - } - else - { - propVal = prop.GetValue(item); - if (propVal == null) return; - } - - var propValEach = propVal as IEnumerable; + var propValEach = GetItemValue(item, prop) as IEnumerable; if (propValEach == null) return; DbSet refSet = GetDbSetObject(tref.RefEntityType); switch (tref.RefType) diff --git a/FreeSql.DbContext/DbSet/DbSetSync.cs b/FreeSql.DbContext/DbSet/DbSetSync.cs index 5be76522..912c29ce 100644 --- a/FreeSql.DbContext/DbSet/DbSetSync.cs +++ b/FreeSql.DbContext/DbSet/DbSetSync.cs @@ -136,34 +136,53 @@ namespace FreeSql } } - static ConcurrentDictionary> _dicLazyIsSetField = new ConcurrentDictionary>(); /// - /// 保存实体的指定 ManyToMany 导航属性 + /// 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + /// 场景:在关闭级联保存功能之后,手工使用本方法 + /// 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + /// 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + /// 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 /// /// 实体对象 /// 属性名 - public void SaveManyToMany(TEntity item, string propertyName) + public void SaveMany(TEntity item, string propertyName) { if (item == null) return; - if (_table.Properties.ContainsKey(propertyName) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}"); + if (string.IsNullOrEmpty(propertyName)) return; + if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}"); if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException($"{_table.Type.FullName} 类型已设置属性 {propertyName} 忽略特性"); + var tref = _table.GetTableRef(propertyName, true); - if (tref.RefType != Internal.Model.TableRefType.ManyToMany) throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 ManyToMany 特性"); + if (tref == null) return; + switch (tref.RefType) + { + case Internal.Model.TableRefType.OneToOne: + case Internal.Model.TableRefType.ManyToOne: + throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 OneToMany 或 ManyToMany 特性"); + } + DbContextExecCommand(); var oldEnable = _db.Options.EnableAddOrUpdateNavigateList; _db.Options.EnableAddOrUpdateNavigateList = false; - AddOrUpdateNavigateList(item, false, propertyName); - _db.Options.EnableAddOrUpdateNavigateList = oldEnable; + try + { + AddOrUpdateNavigateList(item, false, propertyName); + if (tref.RefType == Internal.Model.TableRefType.OneToMany) + { + DbContextExecCommand(); + //删除没有保存的数据 + var propValEach = GetItemValue(item, prop) as IEnumerable; + _db.Orm.Select().AsType(tref.RefEntityType).WhereDynamic(propValEach, true) + .ToDelete().ExecuteAffrows(); + } + } + finally + { + _db.Options.EnableAddOrUpdateNavigateList = oldEnable; + } } - /// - /// 联级保存导航集合 - /// - /// 实体对象 - /// 是否为新增的实体对象 - /// 指定保存的属性 void AddOrUpdateNavigateList(TEntity item, bool isAdd, string propertyName = null) { - Type itemType = null; Action action = prop => { if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return; @@ -178,26 +197,7 @@ namespace FreeSql return; } - object propVal = null; - if (itemType == null) itemType = item.GetType(); - if (_table.TypeLazy != null && itemType == _table.TypeLazy) - { - var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary()).GetOrAdd(prop.Name, propName => - _table.TypeLazy.GetField($"__lazy__{propName}", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance)); - if (lazyField != null) - { - var lazyFieldValue = (bool)lazyField.GetValue(item); - if (lazyFieldValue == false) return; - } - propVal = prop.GetValue(item, null); - } - else - { - propVal = prop.GetValue(item, null); - if (propVal == null) return; - } - - var propValEach = propVal as IEnumerable; + var propValEach = GetItemValue(item, prop) as IEnumerable; if (propValEach == null) return; DbSet refSet = GetDbSetObject(tref.RefEntityType); switch (tref.RefType) @@ -313,6 +313,29 @@ namespace FreeSql else if (_table.Properties.TryGetValue(propertyName, out var prop)) action(prop); } + static ConcurrentDictionary> _dicLazyIsSetField = new ConcurrentDictionary>(); + object GetItemValue(TEntity item, PropertyInfo prop) + { + object propVal = null; + var itemType = item.GetType(); + if (_table.TypeLazy != null && itemType == _table.TypeLazy) + { + var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary()).GetOrAdd(prop.Name, propName => + _table.TypeLazy.GetField($"__lazy__{propName}", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance)); + if (lazyField != null) + { + var lazyFieldValue = (bool)lazyField.GetValue(item); + if (lazyFieldValue == false) return null; + } + propVal = prop.GetValue(item, null); + } + else + { + propVal = prop.GetValue(item, null); + if (propVal == null) return null; + } + return propVal; + } #endregion #region Update diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 1a43f59e..b718b2e5 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -32,9 +32,13 @@ - + - 保存实体的指定 ManyToMany 导航属性 + 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + 场景:在关闭级联保存功能之后,手工使用本方法 + 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 实体对象 属性名 @@ -65,9 +69,9 @@ - 是否开启一对多,多对多联级保存功能 + 是否开启一对多,多对多级联保存功能 - 【一对多】模型下, 保存时可联级保存实体的属性集合。出于使用安全考虑我们没做完整对比,只实现实体属性集合的添加或更新操作,所以不会删除实体属性集合的数据。 + 【一对多】模型下, 保存时可级联保存实体的属性集合。出于使用安全考虑我们没做完整对比,只实现实体属性集合的添加或更新操作,所以不会删除实体属性集合的数据。 完整对比的功能使用起来太危险,试想下面的场景: - 保存的时候,实体的属性集合是空的,如何操作?记录全部删除? - 保存的时候,由于数据库中记录非常之多,那么只想保存子表的部分数据,或者只需要添加,如何操作? @@ -106,34 +110,23 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 - + - 保存实体的指定 ManyToMany 导航属性 + 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + 场景:在关闭级联保存功能之后,手工使用本方法 + 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 实体对象 属性名 - - - 联级保存导航集合 - - 实体对象 - 是否为新增的实体对象 - 指定保存的属性 - 更新 @@ -240,9 +233,13 @@ - + - 保存实体的指定 ManyToMany 导航属性 + 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + 场景:在关闭级联保存功能之后,手工使用本方法 + 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 实体对象 属性名 diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs index 38dd740b..b18a60a6 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs @@ -130,9 +130,9 @@ namespace FreeSql return entity; } - public void SaveManyToMany(TEntity entity, string propertyName) + public void SaveMany(TEntity entity, string propertyName) { - _dbset.SaveManyToMany(entity, propertyName); + _dbset.SaveMany(entity, propertyName); _db.SaveChanges(); } } diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs b/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs index f848f89d..d29433eb 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs @@ -64,9 +64,9 @@ namespace FreeSql return entity; } - async public Task SaveManyToManyAsync(TEntity entity, string propertyName) + async public Task SaveManyAsync(TEntity entity, string propertyName) { - await _dbset.SaveManyToManyAsync(entity, propertyName); + await _dbset.SaveManyAsync(entity, propertyName); await _db.SaveChangesAsync(); } } diff --git a/FreeSql.DbContext/Repository/Repository/IBasicRepository.cs b/FreeSql.DbContext/Repository/Repository/IBasicRepository.cs index 24f7291c..b0b4f804 100644 --- a/FreeSql.DbContext/Repository/Repository/IBasicRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/IBasicRepository.cs @@ -30,11 +30,15 @@ namespace FreeSql TEntity InsertOrUpdate(TEntity entity); /// - /// 保存实体的指定 ManyToMany 导航属性 + /// 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比) + /// 场景:在关闭级联保存功能之后,手工使用本方法 + /// 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus") + /// 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据 + /// 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录 /// /// 实体对象 /// 属性名 - void SaveManyToMany(TEntity entity, string propertyName); + void SaveMany(TEntity entity, string propertyName); IUpdate UpdateDiy { get; } @@ -49,7 +53,7 @@ namespace FreeSql Task UpdateAsync(TEntity entity); Task UpdateAsync(IEnumerable entitys); Task InsertOrUpdateAsync(TEntity entity); - Task SaveManyToManyAsync(TEntity entity, string propertyName); + Task SaveManyAsync(TEntity entity, string propertyName); Task DeleteAsync(TEntity entity); Task DeleteAsync(IEnumerable entitys); diff --git a/FreeSql.DbContext/readme.md b/FreeSql.DbContext/readme.md index 155847e5..beee15e9 100644 --- a/FreeSql.DbContext/readme.md +++ b/FreeSql.DbContext/readme.md @@ -6,7 +6,7 @@ ### v0.6.5 -- 修复 Repository 联级保存的 bug; +- 修复 Repository 级联保存的 bug; - 添加工作单元开启方法; - 适配 .net framework 4.5、netstandard 2.0; @@ -192,7 +192,7 @@ fsql.GetGuidRepository().Select.FromRepository(logRepository) - 修复 AddOrUpdate/InsertOrUpdate 当主键无值时,仍然查询了一次数据库; - 增加 查询数据时 TrackToList 对导航集合的状态跟踪; -- 完善 AddOrUpdateNavigateList 联级保存,忽略标记 IsIgnore 的集合属性; +- 完善 AddOrUpdateNavigateList 级联保存,忽略标记 IsIgnore 的集合属性; - 完成 IFreeSql.Include、IncludeMany 功能; ### v0.5.12 diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs index 4fa4fbe5..3097044b 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs @@ -361,7 +361,9 @@ namespace FreeSql.Tests }) } }; + repo.DbContextOptions.EnableAddOrUpdateNavigateList = false; //رռ湦 repo.Insert(cts); + repo.SaveMany(cts[0], "Childs"); //ָ Childs һԶ cts[0].Name = "11"; cts[0].Childs.Clear(); cts[1].Name = "22"; @@ -415,9 +417,9 @@ namespace FreeSql.Tests } }; var repo = g.sqlite.GetRepository(); - //repo.DbContextOptions.EnableAddOrUpdateNavigateList = false; //ر湦 + //repo.DbContextOptions.EnableAddOrUpdateNavigateList = false; //رռ湦 repo.Insert(ss); - repo.SaveManyToMany(ss[0], "Tags"); //ָ Tags Զ + //repo.SaveMany(ss[0], "Tags"); //ָ Tags Զ ss[0].Name = "һ.mp5"; ss[0].Tags.Clear(); diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs index ea2a7435..bc192e74 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs @@ -98,7 +98,7 @@ namespace FreeSql.Tests var sql = g.mysql.Select().Where(a => a.type == testenumWhereType.Blaaa).ToSql(); var tolist = g.mysql.Select().Where(a => a.type == testenumWhereType.Blaaa).ToList(); - //֧ 1Զ + //֧ 1Զ using (var ctx = new FreeContext(g.sqlite)) { @@ -127,7 +127,7 @@ namespace FreeSql.Tests [Fact] public void Update() { - //ѯ 1Զ࣬ + //ѯ 1Զ࣬ټ using (var ctx = new FreeContext(g.sqlite)) { diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index a773044d..6bc4b8d9 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1431,11 +1431,12 @@ lambda表达式 - + 传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 + 是否标识为NOT diff --git a/FreeSql/Interface/Curd/ISelect/ISelect1.cs b/FreeSql/Interface/Curd/ISelect/ISelect1.cs index ea1db65c..43118b65 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect1.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect1.cs @@ -293,8 +293,9 @@ namespace FreeSql /// 传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} /// /// 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 + /// 是否标识为NOT /// - ISelect WhereDynamic(object dywhere); + ISelect WhereDynamic(object dywhere, bool not = false); /// /// 多表查询时,该方法标记后,表达式条件将对所有表进行附加 diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 8255b6d8..69fce858 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -888,12 +888,16 @@ namespace FreeSql.Internal.CommonProvider public IDelete ToDelete() { if (_tables[0].Table.Primarys.Any() == false) throw new Exception($"ToDelete 功能要求实体类 {_tables[0].Table.CsName} 必须有主键"); - return _orm.Delete().Where(GetToDeleteWhere("ftb_del")); + var del = _orm.Delete(); + if (_tables[0].Table.Type != typeof(T1)) del.AsType(_tables[0].Table.Type); + return del.Where(GetToDeleteWhere("ftb_del")); } public IUpdate ToUpdate() { if (_tables[0].Table.Primarys.Any() == false) throw new Exception($"ToUpdate 功能要求实体类 {_tables[0].Table.CsName} 必须有主键"); - return _orm.Update().Where(GetToDeleteWhere("ftb_upd")); + var upd = _orm.Update(); + if (_tables[0].Table.Type != typeof(T1)) upd.AsType(_tables[0].Table.Type); + return upd.Where(GetToDeleteWhere("ftb_upd")); } protected List> GetTableRuleUnions() diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index db153519..db3be215 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -319,7 +319,9 @@ namespace FreeSql.Internal.CommonProvider _tables[0].Parameter = exp.Parameters[0]; return this.InternalWhere(exp?.Body); } - public ISelect WhereDynamic(object dywhere) => this.Where(_commonUtils.WhereObject(_tables.First().Table, $"{_tables.First().Alias}.", dywhere)); + public ISelect WhereDynamic(object dywhere, bool not = false) => not == false ? + this.Where(_commonUtils.WhereObject(_tables.First().Table, $"{_tables.First().Alias}.", dywhere)) : + this.Where($"not({_commonUtils.WhereObject(_tables.First().Table, $"{_tables.First().Alias}.", dywhere)})"); public ISelect WhereCascade(Expression> exp) {