diff --git a/FreeSql.DbContext/DbContext/DbContext.cs b/FreeSql.DbContext/DbContext/DbContext.cs index c0cceeb4..efcbcc5f 100644 --- a/FreeSql.DbContext/DbContext/DbContext.cs +++ b/FreeSql.DbContext/DbContext/DbContext.cs @@ -46,7 +46,7 @@ namespace FreeSql _optionsPriv = new DbContextOptions(); if (FreeSqlDbContextExtensions._dicSetDbContextOptions.TryGetValue(OrmOriginal.Ado.Identifier, out var opt)) { - _optionsPriv.EnableAddOrUpdateNavigate = opt.EnableAddOrUpdateNavigate; + _optionsPriv.EnableCascadeSave = opt.EnableCascadeSave; _optionsPriv.EnableGlobalFilter = opt.EnableGlobalFilter; _optionsPriv.NoneParameter = opt.NoneParameter; _optionsPriv.OnEntityChange = opt.OnEntityChange; @@ -225,29 +225,29 @@ namespace FreeSql } #if net40 #else - public Task AddAsync(TEntity data) where TEntity : class + public Task AddAsync(TEntity data, CancellationToken cancellationToken = default) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - return this.Set().AddAsync(data); + return this.Set().AddAsync(data, cancellationToken); } - public Task AddRangeAsync(IEnumerable data) where TEntity : class => this.Set().AddRangeAsync(data); + public Task AddRangeAsync(IEnumerable data, CancellationToken cancellationToken = default) where TEntity : class => this.Set().AddRangeAsync(data, cancellationToken); - public Task UpdateAsync(TEntity data) where TEntity : class + public Task UpdateAsync(TEntity data, CancellationToken cancellationToken = default) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - return this.Set().UpdateAsync(data); + return this.Set().UpdateAsync(data, cancellationToken); } - public Task UpdateRangeAsync(IEnumerable data) where TEntity : class => this.Set().UpdateRangeAsync(data); + public Task UpdateRangeAsync(IEnumerable data, CancellationToken cancellationToken = default) where TEntity : class => this.Set().UpdateRangeAsync(data, cancellationToken); - public Task AddOrUpdateAsync(TEntity data) where TEntity : class + public Task AddOrUpdateAsync(TEntity data, CancellationToken cancellationToken = default) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - return this.Set().AddOrUpdateAsync(data); + return this.Set().AddOrUpdateAsync(data, cancellationToken); } - public Task SaveManyAsync(TEntity data, string propertyName) where TEntity : class + public Task SaveManyAsync(TEntity data, string propertyName, CancellationToken cancellationToken = default) where TEntity : class { CheckEntityTypeOrThrow(typeof(TEntity)); - return this.Set().SaveManyAsync(data, propertyName); + return this.Set().SaveManyAsync(data, propertyName, cancellationToken); } #endif #endregion diff --git a/FreeSql.DbContext/DbContext/DbContextOptions.cs b/FreeSql.DbContext/DbContext/DbContextOptions.cs index 741c2139..58ad5407 100644 --- a/FreeSql.DbContext/DbContext/DbContextOptions.cs +++ b/FreeSql.DbContext/DbContext/DbContextOptions.cs @@ -21,16 +21,16 @@ namespace FreeSql /// - 属性集合为空时(!=null),删除他们的所有关联数据(中间表) /// - 属性集合不为空时,与数据库存在的关联数据(中间表)完全对比,计算出应该删除和添加的记录 /// - public bool EnableAddOrUpdateNavigate { get; set; } = false; + public bool EnableCascadeSave { get; set; } = false; /// - /// 因增加支持 OneToOne 级联保存,请了解机制,已改名为 EnableAddOrUpdateNavigate + /// 因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave /// - [Obsolete("因增加支持 OneToOne 级联保存,请了解机制,已改名为 EnableAddOrUpdateNavigate")] + [Obsolete("因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave")] public bool EnableAddOrUpdateNavigateList { - get => EnableAddOrUpdateNavigate; - set => EnableAddOrUpdateNavigate = value; + get => EnableCascadeSave; + set => EnableCascadeSave = value; } /// diff --git a/FreeSql.DbContext/DbSet/DbSet.cs b/FreeSql.DbContext/DbSet/DbSet.cs index 68e72bb0..80d68252 100644 --- a/FreeSql.DbContext/DbSet/DbSet.cs +++ b/FreeSql.DbContext/DbSet/DbSet.cs @@ -166,6 +166,15 @@ namespace FreeSql { ds.AttachRange(_states.Values.OrderBy(a => a.Time).Select(a => a.Value).ToArray()); } + void StatesRemoveByObjects(IEnumerable data) + { + if (data == null) return; + foreach (var item in data) + { + var stateKey = _db.OrmOriginal.GetEntityKeyString(_entityType, item, false); + _states.TryRemove(stateKey, out var trystate); + } + } public class EntityState { diff --git a/FreeSql.DbContext/DbSet/DbSetAsync.cs b/FreeSql.DbContext/DbSet/DbSetAsync.cs index 645600c1..6be0573c 100644 --- a/FreeSql.DbContext/DbSet/DbSetAsync.cs +++ b/FreeSql.DbContext/DbSet/DbSetAsync.cs @@ -55,7 +55,7 @@ namespace FreeSql _db.OrmOriginal.SetEntityValueWithPropertyName(_entityType, data, _tableIdentitys[0].CsName, idtval); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) await AddOrUpdateNavigateAsync(data, true, null, cancellationToken); } else @@ -66,7 +66,7 @@ namespace FreeSql IncrAffrows(1); _db.OrmOriginal.MapEntityValue(_entityType, newval, data); Attach(newval); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) await AddOrUpdateNavigateAsync(data, true, null, cancellationToken); } return; @@ -79,7 +79,7 @@ namespace FreeSql _db.OrmOriginal.SetEntityValueWithPropertyName(_entityType, data, _tableIdentitys[0].CsName, idtval); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) await AddOrUpdateNavigateAsync(data, true, null, cancellationToken); return; } @@ -88,7 +88,7 @@ namespace FreeSql } EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(data)); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) await AddOrUpdateNavigateAsync(data, true, null, cancellationToken); } public Task AddAsync(TEntity data, CancellationToken cancellationToken = default) => AddPrivAsync(data, true, cancellationToken); @@ -121,7 +121,7 @@ namespace FreeSql _db.OrmOriginal.MapEntityValue(_entityType, rets[idx++], s); IncrAffrows(rets.Count); AttachRange(rets); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) await AddOrUpdateNavigateAsync(item, true, null, cancellationToken); return; @@ -139,7 +139,7 @@ namespace FreeSql foreach (var item in data) EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(item)); AttachRange(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) await AddOrUpdateNavigateAsync(item, true, null, cancellationToken); } @@ -161,8 +161,8 @@ namespace FreeSql } await DbContextFlushCommandAsync(cancellationToken); - var oldEnable = _db.Options.EnableAddOrUpdateNavigate; - _db.Options.EnableAddOrUpdateNavigate = false; + var oldEnable = _db.Options.EnableCascadeSave; + _db.Options.EnableCascadeSave = false; try { await AddOrUpdateNavigateAsync(item, false, propertyName, cancellationToken); @@ -198,7 +198,7 @@ namespace FreeSql } finally { - _db.Options.EnableAddOrUpdateNavigate = oldEnable; + _db.Options.EnableCascadeSave = oldEnable; } } async Task AddOrUpdateNavigateAsync(TEntity item, bool isAdd, string propertyName, CancellationToken cancellationToken) @@ -447,7 +447,7 @@ namespace FreeSql state.OldValue = item; EnqueueToDbContext(DbContext.EntityChangeType.Update, state); } - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) await AddOrUpdateNavigateAsync(item, false, null, cancellationToken); } @@ -499,155 +499,11 @@ namespace FreeSql #endregion #region RemoveCascadeAsync - public Task> RemoveCascadeAsync(TEntity data, CancellationToken cancellationToken = default) => RemoveRangeCascadeAsync(new[] { data }, cancellationToken); - public Task> RemoveCascadeAsync(Expression> predicate, CancellationToken cancellationToken = default) => RemoveRangeCascadeAsync(Select.Where(predicate).ToList(), cancellationToken); - async public Task> RemoveRangeCascadeAsync(IEnumerable data, CancellationToken cancellationToken = default) + public Task> RemoveCascadeByDatabaseAsync(Expression> predicate, CancellationToken cancellationToken = default) => RemoveRangeCascadeByMemoryOrDatabaseAsync(Select.Where(predicate).ToList(), false, cancellationToken); + async internal protected Task> RemoveRangeCascadeByMemoryOrDatabaseAsync(IEnumerable data, bool inMemory, CancellationToken cancellationToken = default) { - var returnDeleted = new List(); - if (data?.Any() != true) return returnDeleted; - await DbContextFlushCommandAsync(cancellationToken); - var fsql = _db.Orm; - if (LocalGetNavigates(_table).Any() == false) - { - if (CanRemove(data, true) == false) return returnDeleted; - foreach (var item in data) //防止清除 Identity/Guid - { - var state = CreateEntityState(item); - _states.TryRemove(state.Key, out var trystate); - - EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); - } - await DbContextFlushCommandAsync(cancellationToken); - returnDeleted.AddRange(data.Select(a => (object)a)); - return returnDeleted; - } - - var commonUtils = (fsql.Select() as Internal.CommonProvider.Select0Provider)._commonUtils; - var eachdic = new Dictionary(); - var rootItems = data.Select(a => (object)a).ToArray(); - var rootDbSet = _db.Set(); - rootDbSet.AsType(_table.Type); - rootDbSet.AttachRange(rootItems); - await LocalEachAsync(rootDbSet, rootItems, true); - return returnDeleted; - - List> LocalGetNavigates(TableInfo tb) - { - return tb.Properties.Where(a => tb.ColumnsByCs.ContainsKey(a.Key) == false) - .Select(a => new NativeTuple(tb.GetTableRef(a.Key, false), a.Value)) - .Where(a => a.Item1 != null && a.Item1.RefType != TableRefType.ManyToOne) - .ToList(); - } - async Task LocalEachAsync(DbSet dbset, IEnumerable items, bool isOneToOne) - { - items = items?.Where(item => - { - var itemkeyStr = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(fsql, dbset.EntityType, item, false); - var eachdicKey = $"{dbset.EntityType.FullName},{itemkeyStr}"; - if (eachdic.ContainsKey(eachdicKey)) return false; - eachdic.Add(eachdicKey, true); - return true; - }).ToList(); - if (items?.Any() != true) return; - - var tb = fsql.CodeFirst.GetTableByEntity(dbset.EntityType); - var navs = LocalGetNavigates(tb); - - var otos = navs.Where(a => a.Item1.RefType == TableRefType.OneToOne).ToList(); - if (isOneToOne && otos.Any()) - { - foreach (var oto in otos) - { - var childTable = fsql.CodeFirst.GetTableByEntity(oto.Item1.RefEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(oto.Item1.RefEntityType); - var refitems = items.Select(item => - { - var refitem = oto.Item1.RefEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < oto.Item1.Columns.Count; a++) - { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, oto.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, oto.Item1.RefColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = await childDbSet.Select.Where(commonUtils.WhereItems(oto.Item1.RefColumns.ToArray(), "a.", refitems)).ToListAsync(false, cancellationToken); - await LocalEachAsync(childDbSet, childs, false); - } - } - - var otms = navs.Where(a => a.Item1.RefType == TableRefType.OneToMany).ToList(); - if (otms.Any()) - { - foreach (var otm in otms) - { - var childTable = fsql.CodeFirst.GetTableByEntity(otm.Item1.RefEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(otm.Item1.RefEntityType); - var refitems = items.Select(item => - { - var refitem = otm.Item1.RefEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < otm.Item1.Columns.Count; a++) - { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, otm.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, otm.Item1.RefColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = await childDbSet.Select.Where(commonUtils.WhereItems(otm.Item1.RefColumns.ToArray(), "a.", refitems)).ToListAsync(false, cancellationToken); - await LocalEachAsync(childDbSet, childs, true); - } - } - - var mtms = navs.Where(a => a.Item1.RefType == TableRefType.ManyToMany).ToList(); - if (mtms.Any()) - { - foreach (var mtm in mtms) - { - var childTable = fsql.CodeFirst.GetTableByEntity(mtm.Item1.RefMiddleEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(mtm.Item1.RefMiddleEntityType); - var miditems = items.Select(item => - { - var refitem = mtm.Item1.RefMiddleEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < mtm.Item1.Columns.Count; a++) - { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, mtm.Item1.MiddleColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = await childDbSet.Select.Where(commonUtils.WhereItems(mtm.Item1.MiddleColumns.Take(mtm.Item1.Columns.Count).ToArray(), "a.", miditems)).ToListAsync(false, cancellationToken); - await LocalEachAsync(childDbSet, childs, true); - } - } - - if (dbset == rootDbSet) - { - if (CanRemove(data, true) == false) return; - foreach (var item in data) //防止清除 Identity/Guid - { - var state = CreateEntityState(item); - _states.TryRemove(state.Key, out var trystate); - - EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); - } - await DbContextFlushCommandAsync(cancellationToken); - } - else - { - if (dbset.CanRemove(items, true) == false) return; - foreach (var item in items) //防止清除 Identity/Guid - { - var state = dbset.CreateEntityState(item); - dbset._states.TryRemove(state.Key, out var trystate); - - dbset.EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); - } - await DbContextFlushCommandAsync(cancellationToken); - } - returnDeleted.AddRange(items); - } + //临时调用同步方法,后续会改 + return await Task.FromResult(RemoveRangeCascadeByMemoryOrDatabase(data, inMemory)); } #endregion } diff --git a/FreeSql.DbContext/DbSet/DbSetSync.cs b/FreeSql.DbContext/DbSet/DbSetSync.cs index 68b2af29..740746e0 100644 --- a/FreeSql.DbContext/DbSet/DbSetSync.cs +++ b/FreeSql.DbContext/DbSet/DbSetSync.cs @@ -53,7 +53,7 @@ namespace FreeSql _db.OrmOriginal.SetEntityValueWithPropertyName(_entityType, data, _tableIdentitys[0].CsName, idtval); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) AddOrUpdateNavigate(data, true, null); } else @@ -64,7 +64,7 @@ namespace FreeSql IncrAffrows(1); _db.OrmOriginal.MapEntityValue(_entityType, newval, data); Attach(newval); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) AddOrUpdateNavigate(data, true, null); } return; @@ -77,7 +77,7 @@ namespace FreeSql _db.OrmOriginal.SetEntityValueWithPropertyName(_entityType, data, _tableIdentitys[0].CsName, idtval); _db._entityChangeReport.Add(new DbContext.EntityChangeReport.ChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert }); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) AddOrUpdateNavigate(data, true, null); return; } @@ -86,7 +86,7 @@ namespace FreeSql } EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(data)); Attach(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) AddOrUpdateNavigate(data, true, null); } /// @@ -123,7 +123,7 @@ namespace FreeSql _db.OrmOriginal.MapEntityValue(_entityType, rets[idx++], s); IncrAffrows(rets.Count); AttachRange(rets); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) AddOrUpdateNavigate(item, true, null); return; @@ -141,7 +141,7 @@ namespace FreeSql foreach (var item in data) EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(item)); AttachRange(data); - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) AddOrUpdateNavigate(item, true, null); } @@ -172,8 +172,8 @@ namespace FreeSql } DbContextFlushCommand(); - var oldEnable = _db.Options.EnableAddOrUpdateNavigate; - _db.Options.EnableAddOrUpdateNavigate = false; + var oldEnable = _db.Options.EnableCascadeSave; + _db.Options.EnableCascadeSave = false; try { AddOrUpdateNavigate(item, false, propertyName); @@ -209,7 +209,7 @@ namespace FreeSql } finally { - _db.Options.EnableAddOrUpdateNavigate = oldEnable; + _db.Options.EnableCascadeSave = oldEnable; } } void AddOrUpdateNavigate(TEntity item, bool isAdd, string propertyName) @@ -488,7 +488,7 @@ namespace FreeSql state.OldValue = item; EnqueueToDbContext(DbContext.EntityChangeType.Update, state); } - if (_db.Options.EnableAddOrUpdateNavigate) + if (_db.Options.EnableCascadeSave) foreach (var item in data) AddOrUpdateNavigate(item, false, null); } @@ -510,6 +510,11 @@ namespace FreeSql public void Remove(TEntity data) => RemoveRange(new[] { data }); public void RemoveRange(IEnumerable data) { + if (_db.Options.EnableCascadeSave) + { + RemoveRangeCascadeByMemoryOrDatabase(data, true); + return; + } if (CanRemove(data, true) == false) return; foreach (var item in data) { @@ -608,8 +613,8 @@ namespace FreeSql if (data == null) data = _dataEditing; var beforeAffrows = 0; if (data == null) return 0; - var oldEnable = _db.Options.EnableAddOrUpdateNavigate; - _db.Options.EnableAddOrUpdateNavigate = false; + var oldEnable = _db.Options.EnableCascadeSave; + _db.Options.EnableCascadeSave = false; try { DbContextFlushCommand(); @@ -651,7 +656,7 @@ namespace FreeSql { _dataEditing = null; _statesEditing.Clear(); - _db.Options.EnableAddOrUpdateNavigate = oldEnable; + _db.Options.EnableCascadeSave = oldEnable; } return _db._affrows - beforeAffrows; } @@ -659,33 +664,31 @@ namespace FreeSql #region RemoveCascade /// - /// 根据设置的导航属性,递归查询删除 OneToOne/OneToMany/ManyToMany 数据,并返回已删除的数据 + /// 根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们 /// - /// + /// /// - public List RemoveCascade(TEntity data) => RemoveRangeCascade(new[] { data }); - public List RemoveCascade(Expression> predicate) => RemoveRangeCascade(Select.Where(predicate).ToList()); - public List RemoveRangeCascade(IEnumerable data) + public List RemoveCascadeByDatabase(Expression> predicate) => RemoveRangeCascadeByMemoryOrDatabase(Select.Where(predicate).ToList(), false); + internal protected List RemoveRangeCascadeByMemoryOrDatabase(IEnumerable data, bool inMemory) { - var returnDeleted = new List(); + var returnDeleted = inMemory ? null : new List(); if (data?.Any() != true) return returnDeleted; - DbContextFlushCommand(); - var fsql = _db.Orm; if (LocalGetNavigates(_table).Any() == false) { if (CanRemove(data, true) == false) return returnDeleted; - foreach (var item in data) //防止清除 Identity/Guid + foreach (var item in data) //不直接调用 Remove,防止清除 Identity/Guid { var state = CreateEntityState(item); _states.TryRemove(state.Key, out var trystate); + if (inMemory) _db.OrmOriginal.ClearEntityPrimaryValueWithIdentityAndGuid(_entityType, item); EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); } - DbContextFlushCommand(); - returnDeleted.AddRange(data.Select(a => (object)a)); + returnDeleted?.AddRange(data.Select(a => (object)a)); return returnDeleted; } + var fsql = _db.Orm; var commonUtils = (fsql.Select() as Internal.CommonProvider.Select0Provider)._commonUtils; var eachdic = new Dictionary(); var rootItems = data.Select(a => (object)a).ToArray(); @@ -693,6 +696,7 @@ namespace FreeSql rootDbSet.AsType(_table.Type); rootDbSet.AttachRange(rootItems); LocalEach(rootDbSet, rootItems, true); + rootDbSet.FlushState(); return returnDeleted; List> LocalGetNavigates(TableInfo tb) @@ -722,21 +726,31 @@ namespace FreeSql { foreach (var oto in otos) { - var childTable = fsql.CodeFirst.GetTableByEntity(oto.Item1.RefEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(oto.Item1.RefEntityType); - var refitems = items.Select(item => + var refset = _db.Set(); + refset.AsType(oto.Item1.RefEntityType); + + if (inMemory) { - var refitem = oto.Item1.RefEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < oto.Item1.Columns.Count; a++) + var refitems = items.Select(item => FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, oto.Item2.Name)).Where(item => item != null).ToList(); + refset.AttachRange(refitems); + LocalEach(refset, refitems, false); + } + else + { + var reftb = fsql.CodeFirst.GetTableByEntity(oto.Item1.RefEntityType); + var refwhereItems = items.Select(item => { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, oto.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, oto.Item1.RefColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = childDbSet.Select.Where(commonUtils.WhereItems(oto.Item1.RefColumns.ToArray(), "a.", refitems)).ToList(); - LocalEach(childDbSet, childs, false); + var refitem = oto.Item1.RefEntityType.CreateInstanceGetDefaultValue(); + for (var a = 0; a < oto.Item1.Columns.Count; a++) + { + var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, oto.Item1.Columns[a].CsName); + FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(reftb, refitem, oto.Item1.RefColumns[a].CsName, colval); + } + return refitem; + }).ToList(); + var refitems = refset.Select.Where(commonUtils.WhereItems(oto.Item1.RefColumns.ToArray(), "a.", refwhereItems)).ToList(); + LocalEach(refset, refitems, false); + } } } @@ -745,21 +759,38 @@ namespace FreeSql { foreach (var otm in otms) { - var childTable = fsql.CodeFirst.GetTableByEntity(otm.Item1.RefEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(otm.Item1.RefEntityType); - var refitems = items.Select(item => + var refset = _db.Set(); + refset.AsType(otm.Item1.RefEntityType); + + if (inMemory) { - var refitem = otm.Item1.RefEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < otm.Item1.Columns.Count; a++) + var refitems = items.Select(item => { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, otm.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, otm.Item1.RefColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = childDbSet.Select.Where(commonUtils.WhereItems(otm.Item1.RefColumns.ToArray(), "a.", refitems)).ToList(); - LocalEach(childDbSet, childs, true); + var reflist = new List(); + var reflistie = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, otm.Item2.Name) as IEnumerable; + if (reflistie == null) return null; + foreach (var refitem in reflistie) reflist.Add(refitem); + return reflist; + }).Where(itemlst => itemlst != null).SelectMany(itemlst => itemlst).ToList(); + refset.AttachRange(refitems); + LocalEach(refset, refitems, true); + } + else + { + var reftb = fsql.CodeFirst.GetTableByEntity(otm.Item1.RefEntityType); + var refwhereItems = items.Select(item => + { + var refitem = otm.Item1.RefEntityType.CreateInstanceGetDefaultValue(); + for (var a = 0; a < otm.Item1.Columns.Count; a++) + { + var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, otm.Item1.Columns[a].CsName); + FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(reftb, refitem, otm.Item1.RefColumns[a].CsName, colval); + } + return refitem; + }).ToList(); + var childs = refset.Select.Where(commonUtils.WhereItems(otm.Item1.RefColumns.ToArray(), "a.", refwhereItems)).ToList(); + LocalEach(refset, childs, true); + } } } @@ -768,49 +799,86 @@ namespace FreeSql { foreach (var mtm in mtms) { + var midset = _db.Set(); + midset.AsType(mtm.Item1.RefMiddleEntityType); var childTable = fsql.CodeFirst.GetTableByEntity(mtm.Item1.RefMiddleEntityType); - var childDbSet = _db.Set(); - childDbSet.AsType(mtm.Item1.RefMiddleEntityType); - var miditems = items.Select(item => + + if (inMemory) { - var refitem = mtm.Item1.RefMiddleEntityType.CreateInstanceGetDefaultValue(); - for (var a = 0; a < mtm.Item1.Columns.Count; a++) + var miditems = items.Select(item => { - var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item1.Columns[a].CsName); - FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, mtm.Item1.MiddleColumns[a].CsName, colval); - } - return refitem; - }).ToList(); - var childs = childDbSet.Select.Where(commonUtils.WhereItems(mtm.Item1.MiddleColumns.Take(mtm.Item1.Columns.Count).ToArray(), "a.", miditems)).ToList(); - LocalEach(childDbSet, childs, true); + var midlist = new List(); + var refitems = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item2.Name) as IEnumerable; + if (refitems == null) return null; + var reftb = fsql.CodeFirst.GetTableByEntity(mtm.Item1.RefEntityType); + foreach (var refitem in refitems) + { + var miditem = mtm.Item1.RefMiddleEntityType.CreateInstanceGetDefaultValue(); + for (var a = 0; a < mtm.Item1.Columns.Count; a++) + { + var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item1.Columns[a].CsName); + FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, miditem, mtm.Item1.MiddleColumns[a].CsName, colval); + } + for (var a = 0; a < mtm.Item1.RefColumns.Count; a++) + { + var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(reftb, refitem, mtm.Item1.RefColumns[a].CsName); + FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, miditem, mtm.Item1.MiddleColumns[a + mtm.Item1.Columns.Count].CsName, colval); + } + midlist.Add(miditem); + } + return midlist; + }).Where(midlist => midlist != null).SelectMany(midlist => midlist).ToList(); + midset.AttachRange(miditems); + LocalEach(midset, miditems, true); + } + else + { + var miditems = items.Select(item => + { + var refitem = mtm.Item1.RefMiddleEntityType.CreateInstanceGetDefaultValue(); + for (var a = 0; a < mtm.Item1.Columns.Count; a++) + { + var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item1.Columns[a].CsName); + FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childTable, refitem, mtm.Item1.MiddleColumns[a].CsName, colval); + } + return refitem; + }).ToList(); + var childs = midset.Select.Where(commonUtils.WhereItems(mtm.Item1.MiddleColumns.Take(mtm.Item1.Columns.Count).ToArray(), "a.", miditems)).ToList(); + LocalEach(midset, childs, true); + } } } if (dbset == rootDbSet) { if (CanRemove(data, true) == false) return; - foreach (var item in data) //防止清除 Identity/Guid + foreach (var item in data) //不直接调用 Remove,防止清除 Identity/Guid { var state = CreateEntityState(item); _states.TryRemove(state.Key, out var trystate); + if (inMemory) _db.OrmOriginal.ClearEntityPrimaryValueWithIdentityAndGuid(_entityType, item); EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); } - DbContextFlushCommand(); } else { if (dbset.CanRemove(items, true) == false) return; - foreach (var item in items) //防止清除 Identity/Guid + foreach (var item in items) //不直接调用 dbset.Remove,防止清除 Identity/Guid { var state = dbset.CreateEntityState(item); dbset._states.TryRemove(state.Key, out var trystate); + if (inMemory) _db.OrmOriginal.ClearEntityPrimaryValueWithIdentityAndGuid(dbset.EntityType, item); dbset.EnqueueToDbContext(DbContext.EntityChangeType.Delete, state); } - dbset.DbContextFlushCommand(); + + var rawset = _db.Set(dbset.EntityType); + var statesRemove = typeof(DbSet<>).MakeGenericType(dbset.EntityType).GetMethod("StatesRemoveByObjects", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(IEnumerable) }, null); + if (statesRemove == null) throw new Exception("找不到方法 DbSet<>.StatesRemoveByObjects"); + statesRemove.Invoke(rawset, new object[] { items }); } - returnDeleted.AddRange(items); + returnDeleted?.AddRange(items); } } #endregion diff --git a/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent.cs b/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent.cs index 2374ef73..bed4b4c0 100644 --- a/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent.cs +++ b/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent.cs @@ -242,7 +242,7 @@ namespace FreeSql.Extensions.EfCoreFluentApi } /// - /// 使用 Repository + EnableAddOrUpdateNavigate + NoneParameter 方式插入种子数据 + /// 使用 Repository + EnableCascadeSave + NoneParameter 方式插入种子数据 /// /// /// @@ -263,7 +263,7 @@ namespace FreeSql.Extensions.EfCoreFluentApi if (_fsql.Select().AsType(et).Any()) continue; var repo = _fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.AsType(et); repo.Insert(sd); diff --git a/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent`1.cs b/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent`1.cs index 74fe0662..3cd561ad 100644 --- a/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent`1.cs +++ b/FreeSql.DbContext/EfCoreFluentApi/EfCoreTableFluent`1.cs @@ -329,7 +329,7 @@ namespace FreeSql.Extensions.EfCoreFluentApi public EfCoreTableFluent HasData(T data) => HasData(new[] { data }); /// - /// 使用 Repository + EnableAddOrUpdateNavigate + NoneParameter 方式插入种子数据 + /// 使用 Repository + EnableCascadeSave + NoneParameter 方式插入种子数据 /// /// /// @@ -350,7 +350,7 @@ namespace FreeSql.Extensions.EfCoreFluentApi if (_fsql.Select().AsType(et).Any()) continue; var repo = _fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.AsType(et); repo.Insert(sd); diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index c9355f4b..4c50d954 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -89,7 +89,7 @@ 刷新队列中的命令 - + 是否开启 一对一(OneToOne)、一对多(OneToMany)、多对多(ManyToMany) 级联保存功能 @@ -107,7 +107,7 @@ - 因增加支持 OneToOne 级联保存,请了解机制,已改名为 EnableAddOrUpdateNavigate + 因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave @@ -216,11 +216,11 @@ 可选参数:手工传递最终的 data 值进行对比默认:如果不传递,则使用 BeginEdit 传入的 data 引用进行对比 - + - 根据设置的导航属性,递归查询删除 OneToOne/OneToMany/ManyToMany 数据,并返回已删除的数据 + 根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们 - + @@ -237,7 +237,7 @@ - 使用 Repository + EnableAddOrUpdateNavigate + NoneParameter 方式插入种子数据 + 使用 Repository + EnableCascadeSave + NoneParameter 方式插入种子数据 @@ -250,7 +250,7 @@ - 使用 Repository + EnableAddOrUpdateNavigate + NoneParameter 方式插入种子数据 + 使用 Repository + EnableCascadeSave + NoneParameter 方式插入种子数据 @@ -360,11 +360,11 @@ 实体对象 属性名 - + - 根据设置的导航属性,递归查询删除 OneToOne/OneToMany/ManyToMany 数据,并返回已删除的数据 + 根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们 - + @@ -559,14 +559,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs index c6771de4..287ae219 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepository.cs @@ -94,9 +94,12 @@ namespace FreeSql _dbset.RemoveRange(entitys); return _db.SaveChanges(); } - public List DeleteCascade(TEntity entity) => _dbset.RemoveCascade(entity); - public List DeleteCascade(IEnumerable entitys) => _dbset.RemoveRangeCascade(entitys); - public List DeleteCascade(Expression> predicate) => _dbset.RemoveCascade(predicate); + public List RemoveCascadeByDatabase(Expression> predicate) + { + var list = _dbset.RemoveCascadeByDatabase(predicate); + var affrows = _db.SaveChanges(); + return list; + } public virtual TEntity Insert(TEntity entity) { @@ -192,7 +195,6 @@ namespace FreeSql return ret; } - public virtual List DeleteCascade(TKey id) => _dbset.RemoveCascade(Find(id)); public virtual int Delete(TKey id) => Delete(CheckTKeyAndReturnIdEntity(id)); public virtual TEntity Find(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOne(); public TEntity Get(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOne(); diff --git a/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs b/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs index cb5df42c..02a49839 100644 --- a/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs +++ b/FreeSql.DbContext/Repository/Repository/BaseRepositoryAsync.cs @@ -32,9 +32,12 @@ namespace FreeSql _dbset.RemoveRange(entitys); return _db.SaveChangesAsync(cancellationToken); } - public virtual Task> DeleteCascade(TEntity entity, CancellationToken cancellationToken = default) => _dbset.RemoveCascadeAsync(entity, cancellationToken); - public virtual Task> DeleteCascade(IEnumerable entitys, CancellationToken cancellationToken = default) => _dbset.RemoveRangeCascadeAsync(entitys, cancellationToken); - public virtual Task> DeleteCascade(Expression> predicate, CancellationToken cancellationToken = default) => _dbset.RemoveCascadeAsync(predicate, cancellationToken); + async public virtual Task> RemoveCascadeByDatabaseAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + var list = await _dbset.RemoveCascadeByDatabaseAsync(predicate, cancellationToken); + var affrows = await _db.SaveChangesAsync(cancellationToken); + return list; + } async public virtual Task InsertAsync(TEntity entity, CancellationToken cancellationToken = default) { @@ -76,7 +79,6 @@ namespace FreeSql partial class BaseRepository { - public virtual Task> DeleteCascadeAsync(TKey id, CancellationToken cancellationToken = default) => _dbset.RemoveCascadeAsync(Find(id), cancellationToken); public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) => DeleteAsync(CheckTKeyAndReturnIdEntity(id), cancellationToken); public virtual Task FindAsync(TKey id, CancellationToken cancellationToken = default) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOneAsync(cancellationToken); public Task GetAsync(TKey id, CancellationToken cancellationToken = default) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOneAsync(cancellationToken); diff --git a/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs b/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs index 03edcaa6..fa3c6fda 100644 --- a/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs +++ b/FreeSql.DbContext/Repository/Repository/IBaseRepository.cs @@ -86,13 +86,11 @@ namespace FreeSql int Delete(IEnumerable entitys); int Delete(Expression> predicate); /// - /// 根据设置的导航属性,递归查询删除 OneToOne/OneToMany/ManyToMany 数据,并返回已删除的数据 + /// 根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们 /// - /// + /// /// - List DeleteCascade(TEntity entity); - List DeleteCascade(IEnumerable entitys); - List DeleteCascade(Expression> predicate); + List RemoveCascadeByDatabase(Expression> predicate); /// /// 开始编辑数据,然后调用方法 EndEdit 分析出添加、修改、删除 SQL 语句进行执行 @@ -124,9 +122,7 @@ namespace FreeSql Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default); Task DeleteAsync(IEnumerable entitys, CancellationToken cancellationToken = default); Task DeleteAsync(Expression> predicate, CancellationToken cancellationToken = default); - Task> DeleteCascade(TEntity entity, CancellationToken cancellationToken = default); - Task> DeleteCascade(IEnumerable entitys, CancellationToken cancellationToken = default); - Task> DeleteCascade(Expression> predicate, CancellationToken cancellationToken = default); + Task> RemoveCascadeByDatabaseAsync(Expression> predicate, CancellationToken cancellationToken = default); #endif } @@ -136,14 +132,12 @@ namespace FreeSql TEntity Get(TKey id); TEntity Find(TKey id); int Delete(TKey id); - List DeleteCascade(TKey id); #if net40 #else Task GetAsync(TKey id, CancellationToken cancellationToken = default); Task FindAsync(TKey id, CancellationToken cancellationToken = default); Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); - Task> DeleteCascadeAsync(TKey id, CancellationToken cancellationToken = default); #endif } } \ No newline at end of file diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs index d2d03ca6..8c22404a 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs @@ -13,15 +13,27 @@ namespace FreeSql.Tests public void DeleteCascade() { var fsql = g.sqlite; + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + var groupRepo = fsql.GetRepository(); var userRepo = fsql.GetRepository(); - userRepo.DbContextOptions.EnableAddOrUpdateNavigate = true; - //OneToOne + var userextRepo = fsql.GetRepository(); + var tagRepo = fsql.GetRepository(); + groupRepo.DbContextOptions.EnableCascadeSave = true; + userRepo.DbContextOptions.EnableCascadeSave = true; + userextRepo.DbContextOptions.EnableCascadeSave = true; + tagRepo.DbContextOptions.EnableCascadeSave = true; + + //OneToOne InDatabase fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); var user = new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" } }; userRepo.Insert(user); - var ret = userRepo.DeleteCascade(user); + var ret = userRepo.RemoveCascadeByDatabase(a => a.Id == user.Id); Assert.Equal(2, ret.Count); Assert.IsType(ret[0]); Assert.Equal(user.UserExt.UserId, (ret[0] as DeleteCascadeUserExt).UserId); @@ -30,13 +42,29 @@ namespace FreeSql.Tests Assert.Equal(user.Id, (ret[1] as DeleteCascadeUser).Id); Assert.Equal(user.Username, (ret[1] as DeleteCascadeUser).Username); Assert.Equal(user.Password, (ret[1] as DeleteCascadeUser).Password); - - //OneToOne 先删除 UserExt + //OneToOne EnableCascadeSave InMemory fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); user = new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" } }; userRepo.Insert(user); - ret = fsql.GetRepository().DeleteCascade(user.UserExt); + Assert.True(user.Id > 0); + Assert.True(user.UserExt.UserId > 0); + var affrows = userRepo.Delete(user); + Assert.Equal(2, affrows); + Assert.Equal(0, user.Id); + Assert.Equal("admin01", user.Username); + Assert.Equal("pwd01", user.Password); + Assert.True(user.UserExt.UserId > 0); + Assert.Equal("用户备注01", user.UserExt.Remark); + Assert.False(userRepo.Select.Any()); + Assert.False(userextRepo.Select.Any()); + + //OneToOne InDatabase 先删除 UserExt + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + user = new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" } }; + userRepo.Insert(user); + ret = userextRepo.RemoveCascadeByDatabase(a => a.UserId == user.UserExt.UserId); Assert.Equal(2, ret.Count); Assert.IsType(ret[1]); Assert.Equal(user.UserExt.UserId, (ret[1] as DeleteCascadeUserExt).UserId); @@ -45,12 +73,31 @@ namespace FreeSql.Tests Assert.Equal(user.Id, (ret[0] as DeleteCascadeUser).Id); Assert.Equal(user.Username, (ret[0] as DeleteCascadeUser).Username); Assert.Equal(user.Password, (ret[0] as DeleteCascadeUser).Password); + //OneToOne EnableCascadeSave InMemory 先删除 UserExt + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + user = new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" } }; + userRepo.Insert(user); + Assert.True(user.Id > 0); + Assert.True(user.UserExt.UserId > 0); + var userext = userextRepo.Where(a => a.UserId == user.Id).Include(a => a.User).First(); + Assert.NotNull(userext); + Assert.Equal(user.UserExt.UserId, userext.UserId); + Assert.Equal(user.Id, userext.User.Id); + affrows = userextRepo.Delete(userext); + Assert.Equal(2, affrows); + Assert.Equal(0, userext.User.Id); + Assert.Equal("admin01", userext.User.Username); + Assert.Equal("pwd01", userext.User.Password); + Assert.True(userext.UserId > 0); + Assert.Equal("用户备注01", userext.Remark); + Assert.False(userRepo.Select.Any()); + Assert.False(userextRepo.Select.Any()); - //OneToMany + //OneToMany InDatabase fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); - groupRepo.DbContextOptions.EnableAddOrUpdateNavigate = true; var group = new DeleteCascadeUserGroup { GroupName = "group01", @@ -65,7 +112,7 @@ namespace FreeSql.Tests Assert.Equal(group.Id, group.Users[0].GroupId); Assert.Equal(group.Id, group.Users[1].GroupId); Assert.Equal(group.Id, group.Users[2].GroupId); - ret = groupRepo.DeleteCascade(group); + ret = groupRepo.RemoveCascadeByDatabase(a => a.Id == group.Id); Assert.Equal(7, ret.Count); Assert.IsType(ret[0]); Assert.Equal(group.Users[0].UserExt.UserId, (ret[0] as DeleteCascadeUserExt).UserId); @@ -91,8 +138,48 @@ namespace FreeSql.Tests Assert.IsType(ret[6]); Assert.Equal(group.Id, (ret[6] as DeleteCascadeUserGroup).Id); Assert.Equal(group.GroupName, (ret[6] as DeleteCascadeUserGroup).GroupName); + //OneToMany EnableCascadeSave InMemory + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + group = new DeleteCascadeUserGroup + { + GroupName = "group01", + Users = new List + { + new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" } }, + new DeleteCascadeUser { Username = "admin02", Password = "pwd02", UserExt = new DeleteCascadeUserExt { Remark = "用户备注02" } }, + new DeleteCascadeUser { Username = "admin03", Password = "pwd03", UserExt = new DeleteCascadeUserExt { Remark = "用户备注03" } }, + } + }; + groupRepo.Insert(group); + Assert.Equal(group.Id, group.Users[0].GroupId); + Assert.Equal(group.Id, group.Users[1].GroupId); + Assert.Equal(group.Id, group.Users[2].GroupId); + affrows = groupRepo.Delete(group); + Assert.Equal(7, affrows); + Assert.Equal(0, group.Id); + Assert.Equal("group01", group.GroupName); + Assert.Equal(0, group.Users[0].Id); + Assert.Equal("admin01", group.Users[0].Username); + Assert.Equal("pwd01", group.Users[0].Password); + Assert.True(group.Users[0].UserExt.UserId > 0); + Assert.Equal("用户备注01", group.Users[0].UserExt.Remark); + Assert.Equal(0, group.Users[1].Id); + Assert.Equal("admin02", group.Users[1].Username); + Assert.Equal("pwd02", group.Users[1].Password); + Assert.True(group.Users[1].UserExt.UserId > 0); + Assert.Equal("用户备注02", group.Users[1].UserExt.Remark); + Assert.Equal(0, group.Users[2].Id); + Assert.Equal("admin03", group.Users[2].Username); + Assert.Equal("pwd03", group.Users[2].Password); + Assert.True(group.Users[2].UserExt.UserId > 0); + Assert.Equal("用户备注03", group.Users[2].UserExt.Remark); + Assert.False(groupRepo.Select.Any()); + Assert.False(userRepo.Select.Any()); + Assert.False(userextRepo.Select.Any()); - //ManyToMany + //ManyToMany InDatabase fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Delete().Where("1=1").ExecuteAffrows(); @@ -108,8 +195,8 @@ namespace FreeSql.Tests new DeleteCascadeTag { TagName = "tag07" }, new DeleteCascadeTag { TagName = "tag08" }, }; - fsql.GetRepository().Insert(tags); - groupRepo.DbContextOptions.EnableAddOrUpdateNavigate = true; + tagRepo.Insert(tags); + groupRepo.DbContextOptions.EnableCascadeSave = true; group = new DeleteCascadeUserGroup { GroupName = "group01", @@ -124,7 +211,7 @@ namespace FreeSql.Tests Assert.Equal(group.Id, group.Users[0].GroupId); Assert.Equal(group.Id, group.Users[1].GroupId); Assert.Equal(group.Id, group.Users[2].GroupId); - ret = groupRepo.DeleteCascade(group); + ret = groupRepo.RemoveCascadeByDatabase(a => a.Id == group.Id); Assert.Equal(18, ret.Count); Assert.IsType(ret[0]); @@ -188,6 +275,62 @@ namespace FreeSql.Tests Assert.IsType(ret[17]); Assert.Equal(group.Id, (ret[17] as DeleteCascadeUserGroup).Id); Assert.Equal(group.GroupName, (ret[17] as DeleteCascadeUserGroup).GroupName); + + //ManyToMany EnableCascadeSave InMemory + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + tags = new[] { + new DeleteCascadeTag { TagName = "tag01" }, + new DeleteCascadeTag { TagName = "tag02" }, + new DeleteCascadeTag { TagName = "tag03" }, + new DeleteCascadeTag { TagName = "tag04" }, + new DeleteCascadeTag { TagName = "tag05" }, + new DeleteCascadeTag { TagName = "tag06" }, + new DeleteCascadeTag { TagName = "tag07" }, + new DeleteCascadeTag { TagName = "tag08" }, + }; + tagRepo.Insert(tags); + groupRepo.DbContextOptions.EnableCascadeSave = true; + group = new DeleteCascadeUserGroup + { + GroupName = "group01", + Users = new List + { + new DeleteCascadeUser { Username = "admin01", Password = "pwd01", UserExt = new DeleteCascadeUserExt { Remark = "用户备注01" }, Tags = new List { tags[0], tags[2], tags[3], tags[6] } }, + new DeleteCascadeUser { Username = "admin02", Password = "pwd02", UserExt = new DeleteCascadeUserExt { Remark = "用户备注02" }, Tags = new List { tags[1], tags[2], tags[5] } }, + new DeleteCascadeUser { Username = "admin03", Password = "pwd03", UserExt = new DeleteCascadeUserExt { Remark = "用户备注03" }, Tags = new List { tags[3], tags[4], tags[6], tags[7] } }, + } + }; + groupRepo.Insert(group); + Assert.Equal(group.Id, group.Users[0].GroupId); + Assert.Equal(group.Id, group.Users[1].GroupId); + Assert.Equal(group.Id, group.Users[2].GroupId); + affrows = groupRepo.Delete(group); + Assert.Equal(18, affrows); + Assert.Equal(0, group.Id); + Assert.Equal("group01", group.GroupName); + Assert.Equal(0, group.Users[0].Id); + Assert.Equal("admin01", group.Users[0].Username); + Assert.Equal("pwd01", group.Users[0].Password); + Assert.True(group.Users[0].UserExt.UserId > 0); + Assert.Equal("用户备注01", group.Users[0].UserExt.Remark); + Assert.Equal(0, group.Users[1].Id); + Assert.Equal("admin02", group.Users[1].Username); + Assert.Equal("pwd02", group.Users[1].Password); + Assert.True(group.Users[1].UserExt.UserId > 0); + Assert.Equal("用户备注02", group.Users[1].UserExt.Remark); + Assert.Equal(0, group.Users[2].Id); + Assert.Equal("admin03", group.Users[2].Username); + Assert.Equal("pwd03", group.Users[2].Password); + Assert.True(group.Users[2].UserExt.UserId > 0); + Assert.Equal("用户备注03", group.Users[2].UserExt.Remark); + Assert.False(groupRepo.Select.Any()); + Assert.False(userRepo.Select.Any()); + Assert.False(userextRepo.Select.Any()); + Assert.False(fsql.Select().Any()); } public class DeleteCascadeUser { @@ -465,10 +608,10 @@ namespace FreeSql.Tests } [Fact] - public void EnableAddOrUpdateNavigate_OneToMany() + public void EnableCascadeSave_OneToMany() { var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; var cts = new[] { new Cagetory { @@ -528,10 +671,10 @@ namespace FreeSql.Tests } [Fact] - public void EnableAddOrUpdateNavigate_OneToMany_lazyloading() + public void EnableCascadeSave_OneToMany_lazyloading() { var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; var cts = new[] { new CagetoryLD { @@ -600,7 +743,7 @@ namespace FreeSql.Tests public void SaveMany_OneToMany() { var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = false; //关闭级联保存功能 + repo.DbContextOptions.EnableCascadeSave = false; //关闭级联保存功能 var cts = new[] { new Cagetory { @@ -649,7 +792,7 @@ namespace FreeSql.Tests } [Fact] - public void EnableAddOrUpdateNavigate_OneToMany_Parent() + public void EnableCascadeSave_OneToMany_Parent() { g.sqlite.Delete().Where("1=1").ExecuteAffrows(); var repo = g.sqlite.GetRepository(); @@ -674,7 +817,7 @@ namespace FreeSql.Tests }) } }; - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; //打开级联保存功能 + repo.DbContextOptions.EnableCascadeSave = true; //打开级联保存功能 repo.Insert(cts); var notreelist1 = repo.Select.ToList(); @@ -707,7 +850,7 @@ namespace FreeSql.Tests } [Fact] - public void EnableAddOrUpdateNavigate_ManyToMany() + public void EnableCascadeSave_ManyToMany() { var tags = new[] { new Tag { TagName = "流行" }, @@ -735,7 +878,7 @@ namespace FreeSql.Tests } }; var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; //打开级联保存功能 + repo.DbContextOptions.EnableCascadeSave = true; //打开级联保存功能 repo.Insert(ss); ss[0].Tags[0].TagName = "流行101"; diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs index f143cf05..464eb684 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext/UnitTest1.cs @@ -155,7 +155,7 @@ namespace FreeSql.Tests g.sqlite.SetDbContextOptions(opt => { - //opt.EnableAddOrUpdateNavigate = false; + //opt.EnableCascadeSave = false; }); g.mysql.Insert().AppendData(new testenumWhere { type = testenumWhereType.Blaaa }).ExecuteAffrows(); @@ -167,7 +167,7 @@ namespace FreeSql.Tests using (var ctx = g.sqlite.CreateDbContext()) { - ctx.Options.EnableAddOrUpdateNavigate = true; + ctx.Options.EnableCascadeSave = true; var tags = ctx.Set().Select.IncludeMany(a => a.Tags).ToList(); var tag = new Tag @@ -199,7 +199,7 @@ namespace FreeSql.Tests using (var ctx = g.sqlite.CreateDbContext()) { - ctx.Options.EnableAddOrUpdateNavigate = true; + ctx.Options.EnableCascadeSave = true; var tag = ctx.Set().Select.First(); tag.Tags.Add(new Tag { Name = "sub3" }); tag.Name = Guid.NewGuid().ToString(); diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs index 535ecab6..1d538461 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs @@ -191,7 +191,7 @@ WHERE (exists(SELECT 1 g.gbase.Delete().Where("1=1").ExecuteAffrows(); var repo = g.gbase.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1704,7 +1704,7 @@ WHERE (((cast(a.Id as varchar(8000))) in ( SELECT * FROM (SELECT FIRST 10 b.Titl var fsql = g.gbase; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index 74aa07c6..c499d3ba 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -384,7 +384,7 @@ WHERE (((a.`Name`) in (SELECT s.`Title` as1 g.mysql.Delete().Where("1=1").ExecuteAffrows(); var repo = g.mysql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -2001,7 +2001,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1 var fsql = g.mysql; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs index aa20ecab..9c9e6c52 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs @@ -194,7 +194,7 @@ namespace FreeSql.Tests.Odbc.Dameng g.dameng.Delete().Where("1=1").ExecuteAffrows(); var repo = g.dameng.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1728,7 +1728,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" var fsql = g.dameng; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs index bb0fc271..e83eb917 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs @@ -185,7 +185,7 @@ namespace FreeSql.Tests.Odbc.Default g.odbc.Delete().Where("1=1").ExecuteAffrows(); var repo = g.odbc.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1517,7 +1517,7 @@ WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] var fsql = g.odbc; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs index b1a1dbd3..1750d697 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/KingbaseES/Curd/KingbaseESSelectTest.cs @@ -194,7 +194,7 @@ namespace FreeSql.Tests.Odbc.KingbaseES g.kingbaseES.Delete().Where("1=1").ExecuteAffrows(); var repo = g.kingbaseES.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1677,7 +1677,7 @@ WHERE ((((a.""ID"")::text) in (SELECT b.""TITLE"" var fsql = g.kingbaseES; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs index 281a40c4..3e6cd9b9 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs @@ -294,7 +294,7 @@ namespace FreeSql.Tests.Odbc.MySql g.mysql.Delete().Where("1=1").ExecuteAffrows(); var repo = g.mysql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1881,7 +1881,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1 var fsql = g.mysql; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs index ed312b2b..75f2e3e3 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs @@ -194,7 +194,7 @@ namespace FreeSql.Tests.Odbc.Oracle g.oracle.Delete().Where("1=1").ExecuteAffrows(); var repo = g.oracle.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1720,7 +1720,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" var fsql = g.oracle; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 9fbf33fc..a3c6b50c 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -270,7 +270,7 @@ namespace FreeSql.Tests.Odbc.PostgreSQL g.pgsql.Delete().Where("1=1").ExecuteAffrows(); var repo = g.pgsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1780,7 +1780,7 @@ WHERE ((((a.""id"")::text) in (SELECT b.""title"" var fsql = g.pgsql; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs index 13d5b62b..c539a808 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs @@ -184,7 +184,7 @@ namespace FreeSql.Tests.Odbc.SqlServer g.sqlserver.Delete().Where("1=1").ExecuteAffrows(); var repo = g.sqlserver.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1666,7 +1666,7 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title] var fsql = g.sqlserver; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/UnitTest1.cs index be81bdbe..ced8bfe2 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/UnitTest1.cs @@ -532,7 +532,7 @@ WHERE ROWNUM < 11"; ).ToSql(); - g.mysql.SetDbContextOptions(opt => opt.EnableAddOrUpdateNavigate = true); + g.mysql.SetDbContextOptions(opt => opt.EnableCascadeSave = true); var trepo = g.mysql.GetGuidRepository(); trepo.Insert(new TaskBuild { diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Sqlite.Data/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Sqlite.Data/Sqlite/Curd/SqliteSelectTest.cs index 7888ff6e..15ac7fcc 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Sqlite.Data/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Sqlite.Data/Sqlite/Curd/SqliteSelectTest.cs @@ -234,7 +234,7 @@ namespace FreeSql.Tests.Sqlite g.sqlite.Delete().Where("1=1").ExecuteAffrows(); var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -2072,7 +2072,7 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title"" var fsql = g.sqlite; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs index 81cb894b..f384588e 100644 --- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs @@ -309,7 +309,7 @@ WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 g.dameng.Delete().Where("1=1").ExecuteAffrows(); var repo = g.dameng.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1867,7 +1867,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" var fsql = g.dameng; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs index 8a07d65c..ff767afb 100644 --- a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs @@ -309,7 +309,7 @@ WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 g.firebird.Delete().Where("1=1").ExecuteAffrows(); var repo = g.firebird.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1834,7 +1834,7 @@ WHERE (((cast(a.""ID"" as blob sub_type 1)) in (SELECT FIRST 10 b.""TITLE"" var fsql = g.firebird; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/KingbaseES/Curd/KingbaseESSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/KingbaseES/Curd/KingbaseESSelectTest.cs index fe1a81cc..58e797a0 100644 --- a/FreeSql.Tests/FreeSql.Tests/KingbaseES/Curd/KingbaseESSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/KingbaseES/Curd/KingbaseESSelectTest.cs @@ -194,7 +194,7 @@ namespace FreeSql.Tests.KingbaseES g.kingbaseES.Delete().Where("1=1").ExecuteAffrows(); var repo = g.kingbaseES.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1681,7 +1681,7 @@ WHERE ((((a.""ID"")::text) in (SELECT b.""TITLE"" var fsql = g.kingbaseES; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/Linq/QueryableTest.cs b/FreeSql.Tests/FreeSql.Tests/Linq/QueryableTest.cs index 6d8718e3..44ea5ddd 100644 --- a/FreeSql.Tests/FreeSql.Tests/Linq/QueryableTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Linq/QueryableTest.cs @@ -59,7 +59,7 @@ namespace FreeSql.Tests.Linq } }; var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(sd); Assert.True(fsql.Select().AsQueryable().Any()); diff --git a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs index 4b911823..3c54d207 100644 --- a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs @@ -300,7 +300,7 @@ WHERE (((a.[Name]) in (SELECT s.[Title] as as1 g.msaccess.Delete().Where("1=1").ExecuteAffrows(); var repo = g.msaccess.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1645,7 +1645,7 @@ WHERE (((cstr(a.[Id])) in (SELECT TOP 10 b.[Title] var fsql = g.msaccess; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index d7bbf8ac..b5443e37 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -427,7 +427,7 @@ WHERE (((a.`Name`) in (SELECT s.`Title` as1 g.mysql.Delete().Where("1=1").ExecuteAffrows(); var repo = g.mysql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -2090,7 +2090,7 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1 var fsql = g.mysql; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index 80e880d2..6169e7b6 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -309,7 +309,7 @@ WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 g.oracle.Delete().Where("1=1").ExecuteAffrows(); var repo = g.oracle.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1843,7 +1843,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" var fsql = g.oracle; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index feaebee2..341fe856 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -401,7 +401,7 @@ WHERE (((a.""name"") in (SELECT s.""title"" as1 g.pgsql.Delete().Where("1=1").ExecuteAffrows(); var repo = g.pgsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1927,7 +1927,7 @@ WHERE ((((a.""id"")::text) in (SELECT b.""title"" var fsql = g.pgsql; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs index 55f59af8..c199031a 100644 --- a/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/ShenTong/Curd/ShenTongSelectTest.cs @@ -270,7 +270,7 @@ namespace FreeSql.Tests.ShenTong g.shentong.Delete().Where("1=1").ExecuteAffrows(); var repo = g.shentong.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1789,7 +1789,7 @@ WHERE ((((a.""ID"")::text) in (SELECT b.""TITLE"" var fsql = g.shentong; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 8d98316c..cbe5c814 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -306,7 +306,7 @@ WHERE (((a.[Name]) in (SELECT s.[Title] as1 g.sqlserver.Delete().Where("1=1").ExecuteAffrows(); var repo = g.sqlserver.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -1910,7 +1910,7 @@ INNER JOIN [TestTypeInfo] a__Type With(NoLock) ON a__Type.[Guid] = a.[Id]", sql2 var fsql = g.sqlserver; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index aa1aeb41..a9b3f59b 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -354,7 +354,7 @@ WHERE (((a.""Name"") in (SELECT s.""Title"" as1 g.sqlite.Delete().Where("1=1").ExecuteAffrows(); var repo = g.sqlite.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new District { Code = "001", @@ -2217,7 +2217,7 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title"" var fsql = g.sqlite; fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.DbContextOptions.NoneParameter = true; repo.Insert(new VM_District_Child { diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs index d1f0d46d..6d0e168b 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs @@ -830,7 +830,7 @@ namespace FreeSql.Tests ).ToSql(); - g.sqlite.SetDbContextOptions(opt => opt.EnableAddOrUpdateNavigate = true); + g.sqlite.SetDbContextOptions(opt => opt.EnableCascadeSave = true); var trepo = g.sqlite.GetGuidRepository(); trepo.Insert(new TaskBuild { @@ -1146,7 +1146,7 @@ namespace FreeSql.Tests }; var repo = g.mysql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(neworder); var order = g.mysql.Select().Where(a => a.Id == neworder.Id).ToOne(); //查询订单表 diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs index 07e082d3..0fdc8193 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs @@ -210,7 +210,7 @@ namespace FreeSql.Tests g.sqlite.Delete().Where("1=1").ExecuteAffrows(); g.sqlite.Delete().Where("1=1").ExecuteAffrows(); var tshoprepo = g.sqlite.GetRepository(); - tshoprepo.DbContextOptions.EnableAddOrUpdateNavigate = true; + tshoprepo.DbContextOptions.EnableCascadeSave = true; tshoprepo.Insert(new tcate01[] { new tcate01 { name = "tcate1", tshops = new List{ new tshop01(), new tshop01(), new tshop01() } }, diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest4.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest4.cs index 78273091..f37ea359 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest4.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest4.cs @@ -304,7 +304,7 @@ GROUP BY a.""code"", a.""seqid"", a.""name""", sql); fsql.Delete().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; repo.Insert(new ts_otm_ll_01 { name = "001", diff --git a/README.md b/README.md index 6d4e03f8..87ef78bb 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ fsql.Select().OrderBy(a => Guid.NewGuid()).Limit(10).ToList(); [Transactional] public void Add() { var repo = ioc.GetService>(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; var item = new Tag { Name = "testaddsublist", diff --git a/README.zh-CN.md b/README.zh-CN.md index dd3b450d..a0d1d31c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -135,7 +135,7 @@ fsql.Select().OrderBy(a => Guid.NewGuid()).Limit(10).ToList(); [Transactional] public void Add() { var repo = ioc.GetService>(); - repo.DbContextOptions.EnableAddOrUpdateNavigate = true; + repo.DbContextOptions.EnableCascadeSave = true; var item = new Tag { Name = "testaddsublist",