mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
- 增加 DbContext、Repository SaveManyToMany 方法,实现手工保存 ManyToMany 关联数据;
This commit is contained in:
parent
0f7dd75e64
commit
e26dbfe526
@ -136,6 +136,13 @@ namespace FreeSql
|
||||
/// <param name="data"></param>
|
||||
public void AddOrUpdate<TEntity>(TEntity data) where TEntity : class => this.Set<TEntity>().AddOrUpdate(data);
|
||||
|
||||
/// <summary>
|
||||
/// 保存实体的指定 ManyToMany 导航属性
|
||||
/// </summary>
|
||||
/// <param name="data">实体对象</param>
|
||||
/// <param name="propertyName">属性名</param>
|
||||
public void SaveManyToMany<TEntity>(TEntity data, string propertyName) where TEntity : class => this.Set<TEntity>().SaveManyToMany(data, propertyName);
|
||||
|
||||
/// <summary>
|
||||
/// 附加实体,可用于不查询就更新或删除
|
||||
/// </summary>
|
||||
@ -163,6 +170,7 @@ namespace FreeSql
|
||||
public Task UpdateRangeAsync<TEntity>(IEnumerable<TEntity> data) where TEntity : class => this.Set<TEntity>().UpdateRangeAsync(data);
|
||||
|
||||
public Task AddOrUpdateAsync<TEntity>(TEntity data) where TEntity : class => this.Set<TEntity>().AddOrUpdateAsync(data);
|
||||
public Task SaveManyToManyAsync<TEntity>(TEntity data, string propertyName) where TEntity : class => this.Set<TEntity>().SaveManyToManyAsync(data, propertyName);
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
|
@ -132,44 +132,58 @@ namespace FreeSql
|
||||
await AddOrUpdateNavigateListAsync(item, true);
|
||||
}
|
||||
}
|
||||
async Task AddOrUpdateNavigateListAsync(TEntity item, bool isAdd)
|
||||
|
||||
async public Task SaveManyToManyAsync(TEntity item, string propertyName)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (_table.Properties.ContainsKey(propertyName) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}");
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException($"{_table.Type.FullName} 类型已设置属性 {propertyName} 忽略特性");
|
||||
var tref = _table.GetTableRef(propertyName, true);
|
||||
if (tref.RefType != Internal.Model.TableRefType.ManyToMany) throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 ManyToMany 特性");
|
||||
DbContextExecCommand();
|
||||
var oldEnable = _db.Options.EnableAddOrUpdateNavigateList;
|
||||
_db.Options.EnableAddOrUpdateNavigateList = false;
|
||||
await AddOrUpdateNavigateListAsync(item, false, propertyName);
|
||||
_db.Options.EnableAddOrUpdateNavigateList = oldEnable;
|
||||
}
|
||||
async Task AddOrUpdateNavigateListAsync(TEntity item, bool isAdd, string propertyName = null)
|
||||
{
|
||||
Type itemType = null;
|
||||
foreach (var prop in _table.Properties)
|
||||
Func<PropertyInfo, Task> action = async prop =>
|
||||
{
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Key)) continue;
|
||||
if (_table.ColumnsByCs.ContainsKey(prop.Key)) continue;
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return;
|
||||
if (_table.ColumnsByCs.ContainsKey(prop.Name)) return;
|
||||
|
||||
var tref = _table.GetTableRef(prop.Key, true);
|
||||
if (tref == null) continue;
|
||||
var tref = _table.GetTableRef(prop.Name, true);
|
||||
if (tref == null) return;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
object propVal = null;
|
||||
if (itemType == null) itemType = item.GetType();
|
||||
if (_table.TypeLazy != null && itemType == _table.TypeLazy)
|
||||
{
|
||||
var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary<string, FieldInfo>()).GetOrAdd(prop.Key, propName =>
|
||||
var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary<string, FieldInfo>()).GetOrAdd(prop.Name, propName =>
|
||||
_table.TypeLazy.GetField($"__lazy__{propName}", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
if (lazyField != null)
|
||||
{
|
||||
var lazyFieldValue = (bool)lazyField.GetValue(item);
|
||||
if (lazyFieldValue == false) continue;
|
||||
if (lazyFieldValue == false) return;
|
||||
}
|
||||
propVal = prop.Value.GetValue(item);
|
||||
propVal = prop.GetValue(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
propVal = prop.Value.GetValue(item);
|
||||
if (propVal == null) continue;
|
||||
propVal = prop.GetValue(item);
|
||||
if (propVal == null) return;
|
||||
}
|
||||
|
||||
var propValEach = propVal as IEnumerable;
|
||||
if (propValEach == null) continue;
|
||||
if (propValEach == null) return;
|
||||
DbSet<object> refSet = GetDbSetObject(tref.RefEntityType);
|
||||
switch (tref.RefType)
|
||||
{
|
||||
@ -276,7 +290,13 @@ namespace FreeSql
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(propertyName))
|
||||
foreach (var prop in _table.Properties)
|
||||
await action(prop.Value);
|
||||
else if (_table.Properties.TryGetValue(propertyName, out var prop))
|
||||
await action(prop);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -135,50 +135,70 @@ namespace FreeSql
|
||||
AddOrUpdateNavigateList(item, true);
|
||||
}
|
||||
}
|
||||
|
||||
static ConcurrentDictionary<Type, ConcurrentDictionary<string, FieldInfo>> _dicLazyIsSetField = new ConcurrentDictionary<Type, ConcurrentDictionary<string, FieldInfo>>();
|
||||
/// <summary>
|
||||
/// 保存实体的指定 ManyToMany 导航属性
|
||||
/// </summary>
|
||||
/// <param name="item">实体对象</param>
|
||||
/// <param name="propertyName">属性名</param>
|
||||
public void SaveManyToMany(TEntity item, string propertyName)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (_table.Properties.ContainsKey(propertyName) == false) throw new KeyNotFoundException($"{_table.Type.FullName} 不存在属性 {propertyName}");
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(propertyName)) throw new ArgumentException($"{_table.Type.FullName} 类型已设置属性 {propertyName} 忽略特性");
|
||||
var tref = _table.GetTableRef(propertyName, true);
|
||||
if (tref.RefType != Internal.Model.TableRefType.ManyToMany) throw new ArgumentException($"{_table.Type.FullName} 类型的属性 {propertyName} 不是 ManyToMany 特性");
|
||||
DbContextExecCommand();
|
||||
var oldEnable = _db.Options.EnableAddOrUpdateNavigateList;
|
||||
_db.Options.EnableAddOrUpdateNavigateList = false;
|
||||
AddOrUpdateNavigateList(item, false, propertyName);
|
||||
_db.Options.EnableAddOrUpdateNavigateList = oldEnable;
|
||||
}
|
||||
/// <summary>
|
||||
/// 联级保存导航集合
|
||||
/// </summary>
|
||||
/// <param name="item">实体对象</param>
|
||||
/// <param name="isAdd">是否为新增的实体对象</param>
|
||||
void AddOrUpdateNavigateList(TEntity item, bool isAdd)
|
||||
/// <param name="propertyName">指定保存的属性</param>
|
||||
void AddOrUpdateNavigateList(TEntity item, bool isAdd, string propertyName = null)
|
||||
{
|
||||
Type itemType = null;
|
||||
foreach (var prop in _table.Properties)
|
||||
Action<PropertyInfo> action = prop =>
|
||||
{
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Key)) continue;
|
||||
if (_table.ColumnsByCs.ContainsKey(prop.Key)) continue;
|
||||
if (_table.ColumnsByCsIgnore.ContainsKey(prop.Name)) return;
|
||||
if (_table.ColumnsByCs.ContainsKey(prop.Name)) return;
|
||||
|
||||
var tref = _table.GetTableRef(prop.Key, true);
|
||||
if (tref == null) continue;
|
||||
var tref = _table.GetTableRef(prop.Name, true);
|
||||
if (tref == null) return;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
object propVal = null;
|
||||
if (itemType == null) itemType = item.GetType();
|
||||
if (_table.TypeLazy != null && itemType == _table.TypeLazy)
|
||||
{
|
||||
var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary<string, FieldInfo>()).GetOrAdd(prop.Key, propName =>
|
||||
var lazyField = _dicLazyIsSetField.GetOrAdd(_table.TypeLazy, tl => new ConcurrentDictionary<string, FieldInfo>()).GetOrAdd(prop.Name, propName =>
|
||||
_table.TypeLazy.GetField($"__lazy__{propName}", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
if (lazyField != null)
|
||||
{
|
||||
var lazyFieldValue = (bool)lazyField.GetValue(item);
|
||||
if (lazyFieldValue == false) continue;
|
||||
if (lazyFieldValue == false) return;
|
||||
}
|
||||
propVal = prop.Value.GetValue(item, null);
|
||||
propVal = prop.GetValue(item, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
propVal = prop.Value.GetValue(item, null);
|
||||
if (propVal == null) continue;
|
||||
propVal = prop.GetValue(item, null);
|
||||
if (propVal == null) return;
|
||||
}
|
||||
|
||||
var propValEach = propVal as IEnumerable;
|
||||
if (propValEach == null) continue;
|
||||
if (propValEach == null) return;
|
||||
DbSet<object> refSet = GetDbSetObject(tref.RefEntityType);
|
||||
switch (tref.RefType)
|
||||
{
|
||||
@ -285,7 +305,13 @@ namespace FreeSql
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(propertyName))
|
||||
foreach (var prop in _table.Properties)
|
||||
action(prop.Value);
|
||||
else if (_table.Properties.TryGetValue(propertyName, out var prop))
|
||||
action(prop);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -32,6 +32,13 @@
|
||||
<typeparam name="TEntity"></typeparam>
|
||||
<param name="data"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbContext.SaveManyToMany``1(``0,System.String)">
|
||||
<summary>
|
||||
保存实体的指定 ManyToMany 导航属性
|
||||
</summary>
|
||||
<param name="data">实体对象</param>
|
||||
<param name="propertyName">属性名</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbContext.Attach``1(``0)">
|
||||
<summary>
|
||||
附加实体,可用于不查询就更新或删除
|
||||
@ -99,25 +106,26 @@
|
||||
清空状态数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.RemoveAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||
<summary>
|
||||
根据 lambda 条件删除数据
|
||||
</summary>
|
||||
<param name="predicate"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.Add(`0)">
|
||||
<summary>
|
||||
添加
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.AddOrUpdateNavigateList(`0,System.Boolean)">
|
||||
<member name="M:FreeSql.DbSet`1.SaveManyToMany(`0,System.String)">
|
||||
<summary>
|
||||
保存实体的指定 ManyToMany 导航属性
|
||||
</summary>
|
||||
<param name="item">实体对象</param>
|
||||
<param name="propertyName">属性名</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.AddOrUpdateNavigateList(`0,System.Boolean,System.String)">
|
||||
<summary>
|
||||
联级保存导航集合
|
||||
</summary>
|
||||
<param name="item">实体对象</param>
|
||||
<param name="isAdd">是否为新增的实体对象</param>
|
||||
<param name="propertyName">指定保存的属性</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.Update(`0)">
|
||||
<summary>
|
||||
@ -225,6 +233,13 @@
|
||||
</summary>
|
||||
<param name="data"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IBasicRepository`1.SaveManyToMany(`0,System.String)">
|
||||
<summary>
|
||||
保存实体的指定 ManyToMany 导航属性
|
||||
</summary>
|
||||
<param name="entity">实体对象</param>
|
||||
<param name="propertyName">属性名</param>
|
||||
</member>
|
||||
<member name="P:FreeSql.IUnitOfWork.Enable">
|
||||
<summary>
|
||||
是否启用工作单元
|
||||
|
@ -129,6 +129,12 @@ namespace FreeSql
|
||||
_db.SaveChanges();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void SaveManyToMany(TEntity entity, string propertyName)
|
||||
{
|
||||
_dbset.SaveManyToMany(entity, propertyName);
|
||||
_db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract partial class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IBaseRepository<TEntity, TKey>
|
||||
|
@ -36,7 +36,7 @@ namespace FreeSql
|
||||
async public virtual Task<TEntity> InsertAsync(TEntity entity)
|
||||
{
|
||||
await _dbset.AddAsync(entity);
|
||||
_db.SaveChanges();
|
||||
await _db.SaveChangesAsync();
|
||||
return entity;
|
||||
}
|
||||
async public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys)
|
||||
@ -60,9 +60,15 @@ namespace FreeSql
|
||||
async public Task<TEntity> InsertOrUpdateAsync(TEntity entity)
|
||||
{
|
||||
await _dbset.AddOrUpdateAsync(entity);
|
||||
_db.SaveChanges();
|
||||
await _db.SaveChangesAsync();
|
||||
return entity;
|
||||
}
|
||||
|
||||
async public Task SaveManyToManyAsync(TEntity entity, string propertyName)
|
||||
{
|
||||
await _dbset.SaveManyToManyAsync(entity, propertyName);
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
partial class BaseRepository<TEntity, TKey>
|
||||
|
@ -29,6 +29,12 @@ namespace FreeSql
|
||||
int Update(IEnumerable<TEntity> entitys);
|
||||
|
||||
TEntity InsertOrUpdate(TEntity entity);
|
||||
/// <summary>
|
||||
/// 保存实体的指定 ManyToMany 导航属性
|
||||
/// </summary>
|
||||
/// <param name="entity">实体对象</param>
|
||||
/// <param name="propertyName">属性名</param>
|
||||
void SaveManyToMany(TEntity entity, string propertyName);
|
||||
|
||||
IUpdate<TEntity> UpdateDiy { get; }
|
||||
|
||||
@ -43,6 +49,7 @@ namespace FreeSql
|
||||
Task<int> UpdateAsync(TEntity entity);
|
||||
Task<int> UpdateAsync(IEnumerable<TEntity> entitys);
|
||||
Task<TEntity> InsertOrUpdateAsync(TEntity entity);
|
||||
Task SaveManyToManyAsync(TEntity entity, string propertyName);
|
||||
|
||||
Task<int> DeleteAsync(TEntity entity);
|
||||
Task<int> DeleteAsync(IEnumerable<TEntity> entitys);
|
||||
|
@ -415,7 +415,9 @@ namespace FreeSql.Tests
|
||||
}
|
||||
};
|
||||
var repo = g.sqlite.GetRepository<Song>();
|
||||
//repo.DbContextOptions.EnableAddOrUpdateNavigateList = false; //关闭联级保存功能
|
||||
repo.Insert(ss);
|
||||
repo.SaveManyToMany(ss[0], "Tags"); //指定保存 Tags 多对多属性
|
||||
|
||||
ss[0].Name = "爱你一万年.mp5";
|
||||
ss[0].Tags.Clear();
|
||||
|
Loading…
x
Reference in New Issue
Block a user