mirror of
https://github.com/dotnetcore/FreeSql.git
synced 2026-02-08 01:10:57 +08:00
- 恢复 BaseEntity SaveMany 方法;
This commit is contained in:
@@ -226,6 +226,16 @@ namespace FreeSql
|
||||
return affrows;
|
||||
}
|
||||
|
||||
async public virtual Task SaveManyAsync(TEntity entity, string propertyName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
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);
|
||||
await SaveTrackingChangeAsync(tracking, cancellationToken);
|
||||
Attach(entity); //应该只存储 propertyName 内容
|
||||
}
|
||||
|
||||
async Task<int> SaveTrackingChangeAsync(AggregateRootTrackingChangeInfo tracking, CancellationToken cancellationToken)
|
||||
{
|
||||
var affrows = 0;
|
||||
|
||||
@@ -162,5 +162,18 @@ namespace FreeSql
|
||||
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||
return Repository.InsertOrUpdate(this as TEntity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||
/// 【完整】保存导航属性,子表
|
||||
/// </summary>
|
||||
/// <param name="navigatePropertyName">Navigation property name</param>
|
||||
public virtual void SaveMany(string navigatePropertyName)
|
||||
{
|
||||
if (Repository == null)
|
||||
Repository = Orm.GetRepository<TEntity>();
|
||||
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||
Repository.SaveMany(this as TEntity, navigatePropertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,6 +149,19 @@ namespace FreeSql
|
||||
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||
return Repository.InsertOrUpdateAsync(this as TEntity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||
/// 【完整】保存导航属性,子表
|
||||
/// </summary>
|
||||
/// <param name="navigatePropertyName">Navigation property name</param>
|
||||
public virtual Task SaveManyAsync(string navigatePropertyName)
|
||||
{
|
||||
if (Repository == null)
|
||||
Repository = Orm.GetRepository<TEntity>();
|
||||
Repository.UnitOfWork = _resolveUow?.Invoke();
|
||||
return Repository.SaveManyAsync(this as TEntity, navigatePropertyName);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,13 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.BaseEntity`1.SaveMany(System.String)">
|
||||
<summary>
|
||||
To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||
【完整】保存导航属性,子表
|
||||
</summary>
|
||||
<param name="navigatePropertyName">Navigation property name</param>
|
||||
</member>
|
||||
<member name="T:FreeSql.BaseEntityAsync`2">
|
||||
<summary>
|
||||
Entity base class, including CreateTime/UpdateTime/IsDeleted, the async CRUD methods, and ID primary key definition.
|
||||
@@ -152,6 +159,13 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.BaseEntityAsync`1.SaveManyAsync(System.String)">
|
||||
<summary>
|
||||
To completely save the navigation properties of the entity in the form of sub-tables. <br />
|
||||
【完整】保存导航属性,子表
|
||||
</summary>
|
||||
<param name="navigatePropertyName">Navigation property name</param>
|
||||
</member>
|
||||
<member name="T:FreeSql.BaseEntity">
|
||||
<summary>
|
||||
Entity base class, including CreateTime/UpdateTime/IsDeleted.
|
||||
|
||||
@@ -149,6 +149,65 @@ namespace FreeSql
|
||||
await AddOrUpdateNavigateAsync(item, true, null, cancellationToken);
|
||||
}
|
||||
|
||||
async public Task SaveManyAsync(TEntity item, string propertyName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (string.IsNullOrEmpty(propertyName)) return;
|
||||
if (_table.Properties.TryGetValue(propertyName, out var prop) == false) throw new KeyNotFoundException(DbContextErrorStrings.NotFound_Property(_table.Type.FullName, propertyName));
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException(DbContextErrorStrings.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(DbContextErrorStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName));
|
||||
}
|
||||
|
||||
await DbContextFlushCommandAsync(cancellationToken);
|
||||
var oldEnable = _db.Options.EnableCascadeSave;
|
||||
_db.Options.EnableCascadeSave = false;
|
||||
try
|
||||
{
|
||||
await AddOrUpdateNavigateAsync(item, false, propertyName, cancellationToken);
|
||||
if (tref.RefType == TableRefType.OneToMany)
|
||||
{
|
||||
await DbContextFlushCommandAsync(cancellationToken);
|
||||
//删除没有保存的数据,求出主体的条件
|
||||
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;
|
||||
}
|
||||
await subDelete.ExecuteAffrowsAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_db.Options.EnableCascadeSave = oldEnable;
|
||||
}
|
||||
}
|
||||
|
||||
async Task AddOrUpdateNavigateAsync(TEntity item, bool isAdd, string propertyName, CancellationToken cancellationToken)
|
||||
{
|
||||
Func<PropertyInfo, Task> action = async prop =>
|
||||
|
||||
@@ -68,6 +68,12 @@ namespace FreeSql
|
||||
await _db.SaveChangesAsync(cancellationToken);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public virtual async Task SaveManyAsync(TEntity entity, string propertyName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _dbset.SaveManyAsync(entity, propertyName, cancellationToken);
|
||||
await _db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
partial class BaseRepository<TEntity, TKey>
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace FreeSql
|
||||
Task<int> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
Task<int> UpdateAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default);
|
||||
Task<TEntity> InsertOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
Task SaveManyAsync(TEntity entity, string propertyName, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<int> DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
Task<int> DeleteAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default);
|
||||
|
||||
@@ -5831,6 +5831,36 @@
|
||||
<param name="end"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0)">
|
||||
<summary>
|
||||
field IN (value1)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0)">
|
||||
<summary>
|
||||
field in (value1, value2)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0)">
|
||||
<summary>
|
||||
field in (value1, value2, value3)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0,``0)">
|
||||
<summary>
|
||||
field in (value1, value2, value3, value4)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0,``0,``0,``0,``0)">
|
||||
<summary>
|
||||
field in (value1, value2, value3, value4, value5)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExpressionCallExtensions.In``1(``0,``0[])">
|
||||
<summary>
|
||||
field in (values)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.DisplayCsharp(System.Type,System.Boolean)">
|
||||
<summary>
|
||||
获取 Type 的原始 c# 文本表示
|
||||
@@ -6346,126 +6376,3 @@
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})">
|
||||
<summary>
|
||||
插入数据,传入实体集合
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})">
|
||||
<summary>
|
||||
插入数据,传入实体集合
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="source"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.InsertOrUpdate``1">
|
||||
<summary>
|
||||
插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下:<para></para>
|
||||
MySql 5.6+: on duplicate key update<para></para>
|
||||
PostgreSQL 9.4+: on conflict do update<para></para>
|
||||
SqlServer 2008+: merge into<para></para>
|
||||
Oracle 11+: merge into<para></para>
|
||||
Sqlite: replace into<para></para>
|
||||
DuckDB: on conflict do update<para></para>
|
||||
达梦: merge into<para></para>
|
||||
人大金仓:on conflict do update<para></para>
|
||||
神通:merge into<para></para>
|
||||
MsAccess:不支持<para></para>
|
||||
注意区别:FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性)
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Update``1">
|
||||
<summary>
|
||||
修改数据
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Update``1(System.Object)">
|
||||
<summary>
|
||||
修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Select``1">
|
||||
<summary>
|
||||
查询数据
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Select``1(System.Object)">
|
||||
<summary>
|
||||
查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Delete``1">
|
||||
<summary>
|
||||
删除数据
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Delete``1(System.Object)">
|
||||
<summary>
|
||||
删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Transaction(System.Action)">
|
||||
<summary>
|
||||
开启事务(不支持异步)<para></para>
|
||||
v1.5.0 关闭了线程事务超时自动提交的机制
|
||||
</summary>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.Action)">
|
||||
<summary>
|
||||
开启事务(不支持异步)<para></para>
|
||||
v1.5.0 关闭了线程事务超时自动提交的机制
|
||||
</summary>
|
||||
<param name="isolationLevel"></param>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
<member name="P:IFreeSql.Ado">
|
||||
<summary>
|
||||
数据库访问对象
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IFreeSql.Aop">
|
||||
<summary>
|
||||
所有拦截方法都在这里
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IFreeSql.CodeFirst">
|
||||
<summary>
|
||||
CodeFirst 模式开发相关方法
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IFreeSql.DbFirst">
|
||||
<summary>
|
||||
DbFirst 模式开发相关方法
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IFreeSql.GlobalFilter">
|
||||
<summary>
|
||||
全局过滤设置,可默认附加为 Select/Update/Delete 条件
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
||||
Reference in New Issue
Block a user