- 移除 Repository SaveMany;

This commit is contained in:
2881099 2024-07-24 21:21:30 +08:00
parent 3e3fcf9580
commit b024c54d01
14 changed files with 124 additions and 394 deletions

View File

@ -225,17 +225,6 @@ namespace FreeSql
return affrows; 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) async Task<int> SaveTrackingChangeAsync(AggregateRootTrackingChangeInfo tracking, CancellationToken cancellationToken)
{ {
var affrows = 0; var affrows = 0;

View File

@ -277,17 +277,6 @@ namespace FreeSql
return affrows; return affrows;
} }
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 内容
}
int SaveTrackingChange(AggregateRootTrackingChangeInfo tracking) int SaveTrackingChange(AggregateRootTrackingChangeInfo tracking)
{ {
var affrows = 0; var affrows = 0;

View File

@ -183,20 +183,6 @@ namespace FreeSql
CheckEntityTypeOrThrow(typeof(TEntity)); CheckEntityTypeOrThrow(typeof(TEntity));
this.Set<TEntity>().AddOrUpdate(data); this.Set<TEntity>().AddOrUpdate(data);
} }
/// <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="data">实体对象</param>
/// <param name="propertyName">属性名</param>
public void SaveMany<TEntity>(TEntity data, string propertyName) where TEntity : class
{
CheckEntityTypeOrThrow(typeof(TEntity));
this.Set<TEntity>().SaveMany(data, propertyName);
}
/// <summary> /// <summary>
/// 附加实体,可用于不查询就更新或删除 /// 附加实体,可用于不查询就更新或删除
@ -253,11 +239,6 @@ namespace FreeSql
CheckEntityTypeOrThrow(typeof(TEntity)); CheckEntityTypeOrThrow(typeof(TEntity));
return this.Set<TEntity>().AddOrUpdateAsync(data, cancellationToken); return this.Set<TEntity>().AddOrUpdateAsync(data, cancellationToken);
} }
public Task SaveManyAsync<TEntity>(TEntity data, string propertyName, CancellationToken cancellationToken = default) where TEntity : class
{
CheckEntityTypeOrThrow(typeof(TEntity));
return this.Set<TEntity>().SaveManyAsync(data, propertyName, cancellationToken);
}
#endif #endif
#endregion #endregion

View File

@ -24,16 +24,6 @@ namespace FreeSql
/// </summary> /// </summary>
public bool EnableCascadeSave { get; set; } = false; public bool EnableCascadeSave { get; set; } = false;
/// <summary>
/// 因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave
/// </summary>
[Obsolete("因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave")]
public bool EnableAddOrUpdateNavigateList
{
get => EnableCascadeSave;
set => EnableCascadeSave = value;
}
/// <summary> /// <summary>
/// 使用无参数化设置(对应 IInsert/IUpdate /// 使用无参数化设置(对应 IInsert/IUpdate
/// </summary> /// </summary>

View File

@ -149,64 +149,6 @@ namespace FreeSql
await AddOrUpdateNavigateAsync(item, true, null, cancellationToken); 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(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));
}
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) async Task AddOrUpdateNavigateAsync(TEntity item, bool isAdd, string propertyName, CancellationToken cancellationToken)
{ {
Func<PropertyInfo, Task> action = async prop => Func<PropertyInfo, Task> action = async prop =>

View File

@ -151,73 +151,6 @@ namespace FreeSql
AddOrUpdateNavigate(item, true, null); AddOrUpdateNavigate(item, true, null);
} }
/// <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;
}
}
void AddOrUpdateNavigate(TEntity item, bool isAdd, string propertyName) void AddOrUpdateNavigate(TEntity item, bool isAdd, string propertyName)
{ {
Action<PropertyInfo> action = prop => Action<PropertyInfo> action = prop =>

View File

@ -37,17 +37,6 @@
<typeparam name="TEntity"></typeparam> <typeparam name="TEntity"></typeparam>
<param name="data"></param> <param name="data"></param>
</member> </member>
<member name="M:FreeSql.DbContext.SaveMany``1(``0,System.String)">
<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="data">实体对象</param>
<param name="propertyName">属性名</param>
</member>
<member name="M:FreeSql.DbContext.Attach``1(``0)"> <member name="M:FreeSql.DbContext.Attach``1(``0)">
<summary> <summary>
附加实体,可用于不查询就更新或删除 附加实体,可用于不查询就更新或删除
@ -110,11 +99,6 @@
- 属性集合不为空时,与数据库存在的关联数据(中间表)完全对比,计算出应该删除和添加的记录 - 属性集合不为空时,与数据库存在的关联数据(中间表)完全对比,计算出应该删除和添加的记录
</summary> </summary>
</member> </member>
<member name="P:FreeSql.DbContextOptions.EnableAddOrUpdateNavigateList">
<summary>
因增加支持 OneToOne 级联保存,和基于内存的级联删除,已改名为 EnableCascadeSave
</summary>
</member>
<member name="P:FreeSql.DbContextOptions.NoneParameter"> <member name="P:FreeSql.DbContextOptions.NoneParameter">
<summary> <summary>
使用无参数化设置(对应 IInsert/IUpdate 使用无参数化设置(对应 IInsert/IUpdate
@ -187,17 +171,6 @@
</summary> </summary>
<param name="data"></param> <param name="data"></param>
</member> </member>
<member name="M:FreeSql.DbSet`1.SaveMany(`0,System.String)">
<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>
</member>
<member name="M:FreeSql.DbSet`1.Update(`0)"> <member name="M:FreeSql.DbSet`1.Update(`0)">
<summary> <summary>
更新 更新
@ -507,32 +480,6 @@
FreeSql.Repository Update 失败,因为设置了过滤器 {filterKey}: {filterValueExpression},更新的数据不符合{entityString} FreeSql.Repository Update 失败,因为设置了过滤器 {filterKey}: {filterValueExpression},更新的数据不符合{entityString}
</summary> </summary>
</member> </member>
<member name="M:FreeSql.IRepositoryUnitOfWork.GetRepository``2(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
</summary>
<typeparam name="TEntity"></typeparam>
<typeparam name="TKey"></typeparam>
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSql.IRepositoryUnitOfWork.GetRepository``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
在工作单元内创建联合主键的仓储类,工作单元下的仓储操作具有事务特点
</summary>
<typeparam name="TEntity"></typeparam>
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSql.IRepositoryUnitOfWork.GetGuidRepository``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Func{System.String,System.String})">
<summary>
在工作单元内创建仓库类,工作单元下的仓储操作具有事务特点
</summary>
<typeparam name="TEntity"></typeparam>
<param name="filter">数据过滤 + 验证</param>
<param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
<returns></returns>
</member>
<member name="M:FreeSql.IBaseRepository.AsType(System.Type)"> <member name="M:FreeSql.IBaseRepository.AsType(System.Type)">
<summary> <summary>
动态Type在使用 Repository&lt;object&gt; 后使用本方法,指定实体类型 动态Type在使用 Repository&lt;object&gt; 后使用本方法,指定实体类型
@ -581,17 +528,6 @@
<param name="newdata">最新的实体对象,它将与附加实体的状态对比</param> <param name="newdata">最新的实体对象,它将与附加实体的状态对比</param>
<returns>key: 属性名, value: [旧值, 新值]</returns> <returns>key: 属性名, value: [旧值, 新值]</returns>
</member> </member>
<member name="M:FreeSql.IBaseRepository`1.SaveMany(`0,System.String)">
<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>
</member>
<member name="M:FreeSql.IBaseRepository`1.DeleteCascadeByDatabase(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})"> <member name="M:FreeSql.IBaseRepository`1.DeleteCascadeByDatabase(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary> <summary>
根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们 根据设置的 OneToOne/OneToMany/ManyToMany 导航属性,级联查询所有的数据库记录,删除并返回它们
@ -764,38 +700,17 @@
<param name="that"></param> <param name="that"></param>
<param name="options"></param> <param name="options"></param>
</member> </member>
<member name="M:FreeSqlDbContextExtensions.GetRepository``2(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})"> <member name="M:FreeSqlDbContextExtensions.GetRepository``1(IFreeSql)">
<summary>
返回默认仓库类
</summary>
<typeparam name="TEntity"></typeparam>
<typeparam name="TKey"></typeparam>
<param name="that"></param>
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.GetRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary> <summary>
返回默认仓库类,适用联合主键的仓储类 返回默认仓库类,适用联合主键的仓储类
</summary> </summary>
<typeparam name="TEntity"></typeparam> <typeparam name="TEntity"></typeparam>
<param name="that"></param> <param name="that"></param>
<param name="filter">数据过滤 + 验证</param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.GetGuidRepository``1(IFreeSql,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Func{System.String,System.String})">
<summary>
返回仓库类
</summary>
<typeparam name="TEntity"></typeparam>
<param name="that"></param>
<param name="filter">数据过滤 + 验证</param>
<param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSqlDbContextExtensions.CreateUnitOfWork(IFreeSql)"> <member name="M:FreeSqlDbContextExtensions.CreateUnitOfWork(IFreeSql)">
<summary> <summary>
创建基于仓储功能的工作单元,务必使用 using 包含使用 创建基于工作单元,务必使用 using 包含使用
</summary> </summary>
<param name="that"></param> <param name="that"></param>
<returns></returns> <returns></returns>

View File

@ -1,64 +0,0 @@
using System;
using System.Linq.Expressions;
namespace FreeSql
{
public interface IRepositoryUnitOfWork : IUnitOfWork
{
/// <summary>
/// 在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="filter">数据过滤 + 验证</param>
/// <returns></returns>
IBaseRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
/// <summary>
/// 在工作单元内创建联合主键的仓储类,工作单元下的仓储操作具有事务特点
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="filter">数据过滤 + 验证</param>
/// <returns></returns>
IBaseRepository<TEntity> GetRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
/// <summary>
/// 在工作单元内创建仓库类,工作单元下的仓储操作具有事务特点
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="filter">数据过滤 + 验证</param>
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
/// <returns></returns>
IBaseRepository<TEntity, Guid> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class;
}
class RepositoryUnitOfWork : UnitOfWork, IRepositoryUnitOfWork
{
public RepositoryUnitOfWork(IFreeSql fsql) : base(fsql)
{
}
public IBaseRepository<TEntity, Guid> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class
{
var repo = new GuidRepository<TEntity>(_fsql, filter, asTable);
repo.UnitOfWork = this;
return repo;
}
public IBaseRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class
{
var repo = new DefaultRepository<TEntity, TKey>(_fsql, filter);
repo.UnitOfWork = this;
return repo;
}
public IBaseRepository<TEntity> GetRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class
{
var repo = new DefaultRepository<TEntity, int>(_fsql, filter);
repo.UnitOfWork = this;
return repo;
}
}
}

View File

@ -5,52 +5,24 @@ using System.Linq.Expressions;
partial class FreeSqlDbContextExtensions partial class FreeSqlDbContextExtensions
{ {
/// <summary>
/// 返回默认仓库类
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="that"></param>
/// <param name="filter">数据过滤 + 验证</param>
/// <returns></returns>
public static IBaseRepository<TEntity, TKey> GetRepository<TEntity, TKey>(this IFreeSql that, Expression<Func<TEntity, bool>> filter = null) where TEntity : class
{
return new DefaultRepository<TEntity, TKey>(that, filter);
}
/// <summary> /// <summary>
/// 返回默认仓库类,适用联合主键的仓储类 /// 返回默认仓库类,适用联合主键的仓储类
/// </summary> /// </summary>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
/// <param name="that"></param> /// <param name="that"></param>
/// <param name="filter">数据过滤 + 验证</param>
/// <returns></returns> /// <returns></returns>
public static IBaseRepository<TEntity> GetRepository<TEntity>(this IFreeSql that, Expression<Func<TEntity, bool>> filter = null) where TEntity : class public static IBaseRepository<TEntity> GetRepository<TEntity>(this IFreeSql that) where TEntity : class
{ {
return new DefaultRepository<TEntity, int>(that, filter); return new DefaultRepository<TEntity, int>(that);
} }
/// <summary> /// <summary>
/// 返回仓库类 /// 创建基于工作单元,务必使用 using 包含使用
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="that"></param>
/// <param name="filter">数据过滤 + 验证</param>
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
/// <returns></returns>
public static IBaseRepository<TEntity, Guid> GetGuidRepository<TEntity>(this IFreeSql that, Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class
{
return new GuidRepository<TEntity>(that, filter, asTable);
}
/// <summary>
/// 创建基于仓储功能的工作单元,务必使用 using 包含使用
/// </summary> /// </summary>
/// <param name="that"></param> /// <param name="that"></param>
/// <returns></returns> /// <returns></returns>
public static IRepositoryUnitOfWork CreateUnitOfWork(this IFreeSql that) public static IUnitOfWork CreateUnitOfWork(this IFreeSql that)
{ {
return new RepositoryUnitOfWork(that); return new UnitOfWork(that);
} }
} }

View File

@ -19,10 +19,9 @@ namespace FreeSql
internal Func<Type, string, string> _asTablePriv; internal Func<Type, string, string> _asTablePriv;
protected BaseRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable = null) protected BaseRepository(IFreeSql fsql)
{ {
_ormScoped = DbContextScopedFreeSql.Create(fsql, () => _db, () => UnitOfWork); _ormScoped = DbContextScopedFreeSql.Create(fsql, () => _db, () => UnitOfWork);
AsTable(asTable);
} }
~BaseRepository() => this.Dispose(); ~BaseRepository() => this.Dispose();
@ -143,12 +142,6 @@ namespace FreeSql
return 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 void BeginEdit(List<TEntity> data) => _dbset.BeginEdit(data);
public virtual int EndEdit(List<TEntity> data = null) public virtual int EndEdit(List<TEntity> data = null)
{ {
@ -184,7 +177,7 @@ namespace FreeSql
public abstract partial class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IBaseRepository<TEntity, TKey> public abstract partial class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IBaseRepository<TEntity, TKey>
where TEntity : class where TEntity : class
{ {
public BaseRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable = null) : base(fsql, filter, asTable) { } public BaseRepository(IFreeSql fsql) : base(fsql) { }
TEntity CheckTKeyAndReturnIdEntity(TKey id) TEntity CheckTKeyAndReturnIdEntity(TKey id)
{ {

View File

@ -68,12 +68,6 @@ namespace FreeSql
await _db.SaveChangesAsync(cancellationToken); await _db.SaveChangesAsync(cancellationToken);
return entity; 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> partial class BaseRepository<TEntity, TKey>

View File

@ -3,21 +3,19 @@ using System.Linq.Expressions;
namespace FreeSql namespace FreeSql
{ {
public class DefaultRepository<TEntity, TKey> : BaseRepository<TEntity, TKey> where TEntity : class class DefaultRepository<TEntity, TKey> : BaseRepository<TEntity, TKey> where TEntity : class
{ {
public DefaultRepository(IFreeSql fsql) : base(fsql, null, null) { } public DefaultRepository(IFreeSql fsql) : base(fsql) { }
public DefaultRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter) : base(fsql, filter, null) { } public DefaultRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql)
public DefaultRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql, null, null)
{ {
uowManger?.Binding(this); uowManger?.Binding(this);
} }
} }
public class GuidRepository<TEntity> : BaseRepository<TEntity, Guid> where TEntity : class class GuidRepository<TEntity> : BaseRepository<TEntity, Guid> where TEntity : class
{ {
public GuidRepository(IFreeSql fsql) : this(fsql, null, null) { } public GuidRepository(IFreeSql fsql) : base(fsql) { }
public GuidRepository(IFreeSql fsql, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable) : base(fsql, filter, asTable) { } public GuidRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql)
public GuidRepository(IFreeSql fsql, UnitOfWorkManager uowManger) : base(uowManger?.Orm ?? fsql, null, null)
{ {
uowManger?.Binding(this); uowManger?.Binding(this);
} }

View File

@ -73,16 +73,6 @@ namespace FreeSql
int Update(IEnumerable<TEntity> entitys); int Update(IEnumerable<TEntity> entitys);
TEntity InsertOrUpdate(TEntity entity); TEntity InsertOrUpdate(TEntity entity);
/// <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);
IUpdate<TEntity> UpdateDiy { get; } IUpdate<TEntity> UpdateDiy { get; }
@ -121,7 +111,6 @@ namespace FreeSql
Task<int> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default); Task<int> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<int> UpdateAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default); Task<int> UpdateAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default);
Task<TEntity> InsertOrUpdateAsync(TEntity entity, 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(TEntity entity, CancellationToken cancellationToken = default);
Task<int> DeleteAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default); Task<int> DeleteAsync(IEnumerable<TEntity> entitys, CancellationToken cancellationToken = default);

View File

@ -1104,6 +1104,93 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder">
<summary>
动态创建实体类型
</summary>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.#ctor(IFreeSql,System.String,System.Attribute[])">
<summary>
配置Class
</summary>
<param name="className">类名</param>
<param name="attributes">类标记的特性[Table(Name = "xxx")] [Index(xxxx)]</param>
<returns></returns>
</member>
<member name="P:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.TypeBuilder">
<summary>
获取类型构建器可作为要构建的Type来引用
</summary>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Attribute[])">
<summary>
配置属性
</summary>
<param name="propertyName">属性名称</param>
<param name="propertyType">属性类型</param>
<param name="attributes">属性标记的特性-支持多个</param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Boolean,System.Attribute[])">
<summary>
配置属性
</summary>
<param name="propertyName">属性名称</param>
<param name="propertyType">属性类型</param>
<param name="isOverride">该属性是否重写父类属性</param>
<param name="attributes">属性标记的特性-支持多个</param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Property(System.String,System.Type,System.Boolean,System.Object,System.Attribute[])">
<summary>
配置属性
</summary>
<param name="propertyName">属性名称</param>
<param name="propertyType">属性类型</param>
<param name="isOverride">该属性是否重写父类属性</param>
<param name="defaultValue">属性默认值</param>
<param name="attributes">属性标记的特性-支持多个</param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Extend(System.Type)">
<summary>
配置父类
</summary>
<param name="superClass">父类类型</param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.OverrideProperty(System.Reflection.Emit.TypeBuilder@,System.Reflection.Emit.MethodBuilder,FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.PropertyMethodEnum,System.String)">
<summary>
Override属性
</summary>
<param name="typeBuilder"></param>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.Build">
<summary>
Emit动态创建出Class - Type
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.BuildJustType">
<summary>
Emit动态创建出Class - Type不附带获取TableInfo
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.FirstCharToLower(System.String)">
<summary>
首字母小写
</summary>
<param name="input"></param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.DynamicEntity.DynamicCompileBuilder.FirstCharToUpper(System.String)">
<summary>
首字母大写
</summary>
<param name="input"></param>
<returns></returns>
</member>
<member name="M:FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(IFreeSql,System.Type,System.Object,System.Boolean,System.String)"> <member name="M:FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(IFreeSql,System.Type,System.Object,System.Boolean,System.String)">
<summary> <summary>
获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 "" 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 ""
@ -5826,6 +5913,28 @@
请使用 fsql.InsertDict(dict) 方法插入字典数据 请使用 fsql.InsertDict(dict) 方法插入字典数据
</summary> </summary>
</member> </member>
<member name="M:FreeSqlGlobalDynamicEntityExtensions.DynamicEntity(FreeSql.ICodeFirst,System.String,System.Attribute[])">
<summary>
动态构建Class Type
</summary>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalDynamicEntityExtensions.CreateInstance(FreeSql.Internal.Model.TableInfo,System.Collections.Generic.Dictionary{System.String,System.Object})">
<summary>
根据字典,创建 table 对应的实体对象
</summary>
<param name="table"></param>
<param name="dict"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalDynamicEntityExtensions.CreateDictionary(FreeSql.Internal.Model.TableInfo,System.Object)">
<summary>
根据实体对象,创建 table 对应的字典
</summary>
<param name="table"></param>
<param name="instance"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExpressionCallExtensions.Between(System.DateTime,System.DateTime,System.DateTime)"> <member name="M:FreeSqlGlobalExpressionCallExtensions.Between(System.DateTime,System.DateTime,System.DateTime)">
<summary> <summary>
C# that >= between &amp;&amp; that &lt;= and<para></para> C# that >= between &amp;&amp; that &lt;= and<para></para>