Skip to content

Commit

Permalink
- 恢复 IBaseRepository SaveMany 方法;
Browse files Browse the repository at this point in the history
  • Loading branch information
2881099 committed Aug 20, 2024
1 parent dd4aa02 commit 528d8a3
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ namespace FreeSql
{
partial class AggregateRootRepository<TEntity>
{
public virtual void SaveMany(TEntity entity, string propertyName)
{
var tracking = new AggregateRootTrackingChangeInfo();
var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
if (_states.TryGetValue(stateKey, out var state) == false) throw new Exception($"AggregateRootRepository 使用仓储对象查询后,才可以保存数据 {Orm.GetEntityString(EntityType, entity)}");
AggregateRootUtils.CompareEntityValue(_boundaryName, Orm, EntityType, state.Value, entity, propertyName, tracking);
SaveTrackingChange(tracking);
Attach(entity); //应该只存储 propertyName 内容
}

#region BeginEdit/EndEdit
List<TEntity> _dataEditing;
Expand Down
68 changes: 68 additions & 0 deletions FreeSql.DbContext/DbSet/DbSetSync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -843,5 +843,73 @@ void LocalEach(DbSet<object> dbset, IEnumerable<object> items, bool isOneToOne)
}
}
#endregion

/// <summary>
/// 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比)<para></para>
/// 场景:在关闭级联保存功能之后,手工使用本方法<para></para>
/// 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus")<para></para>
/// 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据<para></para>
/// 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录
/// </summary>
/// <param name="item">实体对象</param>
/// <param name="propertyName">属性名</param>
public void SaveMany(TEntity item, string propertyName)
{
if (item == null) return;
if (string.IsNullOrEmpty(propertyName)) return;
if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException(DbContextStrings.NotFound_Property(_table.Type.FullName, propertyName));
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException(DbContextStrings.TypeHasSetProperty_IgnoreAttribute(_table.Type.FullName, propertyName));

var tref = _table.GetTableRef(propertyName, true, false);
if (tref == null) return;
switch (tref.RefType)
{
case TableRefType.OneToOne:
case TableRefType.ManyToOne:
case TableRefType.PgArrayToMany:
throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName));
}

DbContextFlushCommand();
var oldEnable = _db.Options.EnableCascadeSave;
_db.Options.EnableCascadeSave = false;
try
{
AddOrUpdateNavigate(item, false, propertyName);
if (tref.RefType == TableRefType.OneToMany)
{
DbContextFlushCommand();
//删除没有保存的数据,求出主体的条件
var deleteWhereParentParam = Expression.Parameter(typeof(object), "a");
Expression whereParentExp = null;
for (var colidx = 0; colidx < tref.Columns.Count; colidx++)
{
var whereExp = Expression.Equal(
Expression.MakeMemberAccess(Expression.Convert(deleteWhereParentParam, tref.RefEntityType), tref.RefColumns[colidx].Table.Properties[tref.RefColumns[colidx].CsName]),
Expression.Constant(
FreeSql.Internal.Utils.GetDataReaderValue(
tref.Columns[colidx].CsType,
_db.OrmOriginal.GetEntityValueWithPropertyName(_table.Type, item, tref.Columns[colidx].CsName)), tref.RefColumns[colidx].CsType)
);
if (whereParentExp == null) whereParentExp = whereExp;
else whereParentExp = Expression.AndAlso(whereParentExp, whereExp);
}
var propValEach = GetItemValue(item, prop) as IEnumerable;
var subDelete = _db.OrmOriginal.Delete<object>().AsType(tref.RefEntityType)
.WithTransaction(_uow?.GetOrBeginTransaction())
.Where(Expression.Lambda<Func<object, bool>>(whereParentExp, deleteWhereParentParam));
foreach (var propValItem in propValEach)
{
subDelete.WhereDynamic(propValEach, true);
break;
}
subDelete.ExecuteAffrows();
}
}
finally
{
_db.Options.EnableCascadeSave = oldEnable;
}
}
}
}
22 changes: 22 additions & 0 deletions FreeSql.DbContext/FreeSql.DbContext.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions FreeSql.DbContext/Repository/Repository/BaseRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ public virtual TEntity InsertOrUpdate(TEntity entity)
return entity;
}

public virtual void SaveMany(TEntity entity, string propertyName)
{
_dbset.SaveMany(entity, propertyName);
_db.SaveChanges();
}

public virtual void BeginEdit(List<TEntity> data) => _dbset.BeginEdit(data);
public virtual int EndEdit(List<TEntity> data = null)
{
Expand Down
11 changes: 11 additions & 0 deletions FreeSql.DbContext/Repository/Repository/IBaseRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ public interface IBaseRepository<TEntity> : IBaseRepository
/// <returns></returns>
List<object> DeleteCascadeByDatabase(Expression<Func<TEntity, bool>> predicate);

/// <summary>
/// 保存实体的指定 ManyToMany/OneToMany 导航属性(完整对比)<para></para>
/// 场景:在关闭级联保存功能之后,手工使用本方法<para></para>
/// 例子:保存商品的 OneToMany 集合属性,SaveMany(goods, "Skus")<para></para>
/// 当 goods.Skus 为空(非null)时,会删除表中已存在的所有数据<para></para>
/// 当 goods.Skus 不为空(非null)时,添加/更新后,删除表中不存在 Skus 集合属性的所有记录
/// </summary>
/// <param name="entity">实体对象</param>
/// <param name="propertyName">属性名</param>
void SaveMany(TEntity entity, string propertyName);

/// <summary>
/// 开始编辑数据,然后调用方法 EndEdit 分析出添加、修改、删除 SQL 语句进行执行<para></para>
/// 场景:winform 加载表数据后,一顿添加、修改、删除操作之后,最后才点击【保存】<para></para><para></para>
Expand Down
Loading

0 comments on commit 528d8a3

Please sign in to comment.