From 5d9afe8329013e06d8ece7cc2a089a10e793b180 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Tue, 29 Mar 2022 21:13:45 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20InsertOrUpdateDict=20?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E6=93=8D=E4=BD=9C=E6=96=B9=E6=B3=95=EF=BC=9B?= =?UTF-8?q?#481?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/FreeSql.DbContext.xml | 9 ++ .../SqlServer/Curd/SqlServerInsertTest.cs | 6 ++ FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 100 +++++++++++++++++- FreeSql/FreeSql.xml | 23 ++++ FreeSql/Interface/Curd/IInsertOrUpdate.cs | 6 ++ .../CommonProvider/InsertOrUpdateProvider.cs | 15 ++- 6 files changed, 153 insertions(+), 6 deletions(-) diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index da7ace6b..bdd16ff9 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -538,5 +538,14 @@ + + + 批量注入 Repository,可以参考代码自行调整 + + + + + + diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs index 5849fa92..63fd18b2 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertTest.cs @@ -78,6 +78,12 @@ namespace FreeSql.Tests.SqlServer dicRet = fsql.DeleteDict(diclist).AsTable("table1dict").ExecuteDeleted(); dicRet = fsql.InsertDict(diclist).AsTable("table1dict").NoneParameter().ExecuteInserted(); dicRet = fsql.DeleteDict(diclist).AsTable("table1dict").ExecuteDeleted(); + + sql1 = fsql.InsertOrUpdateDict(dic).AsTable("table1").WherePrimary("id").ToSql(); + sql2 = fsql.InsertOrUpdateDict(diclist).AsTable("table1").WherePrimary("id").ToSql(); + + sql1 = fsql.InsertOrUpdateDict(dic).AsTable("table1").WherePrimary("name").ToSql(); + sql2 = fsql.InsertOrUpdateDict(diclist).AsTable("table1").WherePrimary("name").ToSql(); } [Fact] diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index f4f2eae7..df2ea79d 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -655,7 +655,7 @@ SELECT "); } #endregion - #region IFreeSql Insert/Update/Delete Dictionary + #region IFreeSql Insert/Update/InsertOrUpdate/Delete Dictionary /// /// 插入数据字典 Dictionary<string, object> /// @@ -701,6 +701,32 @@ SELECT "); return updateDict; } /// + /// 插入或更新数据字典,此功能依赖数据库特性(低版本可能不支持),参考如下: + /// MySql 5.6+: on duplicate key update + /// PostgreSQL 9.4+: on conflict do update + /// SqlServer 2008+: merge into + /// Oracle 11+: merge into + /// Sqlite: replace into + /// 达梦: merge into + /// 人大金仓:on conflict do update + /// 神通:merge into + /// MsAccess:不支持 + /// + /// + /// + public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, Dictionary source) + { + var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql); + insertOrUpdateDict._insertOrUpdateProvider.SetSource(source); + return insertOrUpdateDict; + } + public static InsertOrUpdateDictImpl InsertOrUpdateDict(this IFreeSql freesql, IEnumerable> source) + { + var insertOrUpdateDict = new InsertOrUpdateDictImpl(freesql); + insertOrUpdateDict._insertOrUpdateProvider.SetSource(source); + return insertOrUpdateDict; + } + /// /// 删除数据字典 Dictionary<string, object> /// /// @@ -739,6 +765,7 @@ SELECT "); return deleteDict ?? new DeleteDictImpl(freesql); } + #region InsertDictImpl public class InsertDictImpl { internal readonly InsertProvider> _insertProvider; @@ -802,6 +829,9 @@ SELECT "); return this; } } + #endregion + + #region UpdateDictImpl public class UpdateDictImpl { internal readonly UpdateProvider> _updateProvider; @@ -827,6 +857,15 @@ SELECT "); } return pks.ToArray(); } + public static void SetTablePrimary(TableInfo table, params string[] primarys) + { + foreach (var primary in primarys) + { + if (table.ColumnsByCs.TryGetValue(string.Concat(primary), out var col)) col.Attribute.IsPrimary = true; + else throw new Exception($"GetPrimarys 传递的参数 \"{primary}\" 不正确,它不属于字典数据的键名"); + } + table.Primarys = table.Columns.Where(a => a.Value.Attribute.IsPrimary).Select(a => a.Value).ToArray(); + } public UpdateDictImpl AsTable(string tableName) { @@ -879,6 +918,63 @@ SELECT "); return this; } } + #endregion + + #region InsertOrUpdateDictImpl + public class InsertOrUpdateDictImpl + { + internal readonly InsertOrUpdateProvider> _insertOrUpdateProvider; + internal InsertOrUpdateDictImpl(IFreeSql orm) + { + _insertOrUpdateProvider = (orm as BaseDbProvider ?? throw new Exception("IFreeSql 无法转换成 BaseDbProvider")) + .CreateInsertOrUpdateProvider>() as InsertOrUpdateProvider>; + } + + public InsertOrUpdateDictImpl WherePrimary(params string[] primarys) + { + UpdateDictImpl.SetTablePrimary(_insertOrUpdateProvider._table, primarys); + return this; + } + + public InsertOrUpdateDictImpl AsTable(string tableName) + { + _insertOrUpdateProvider.AsTable(tableName); + return this; + } + + public InsertOrUpdateDictImpl CommandTimeout(int timeout) + { + _insertOrUpdateProvider.CommandTimeout(timeout); + return this; + } + + public int ExecuteAffrows() => _insertOrUpdateProvider.ExecuteAffrows(); +#if net40 +#else + public Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => _insertOrUpdateProvider.ExecuteAffrowsAsync(cancellationToken); +#endif + public InsertOrUpdateDictImpl IfExistsDoNothing() + { + _insertOrUpdateProvider.IfExistsDoNothing(); + return this; + } + + public string ToSql() => _insertOrUpdateProvider.ToSql(); + + public InsertOrUpdateDictImpl WithConnection(DbConnection connection) + { + _insertOrUpdateProvider.WithConnection(connection); + return this; + } + public InsertOrUpdateDictImpl WithTransaction(DbTransaction transaction) + { + _insertOrUpdateProvider.WithTransaction(transaction); + return this; + } + } + #endregion + + #region DeleteDictImpl public class DeleteDictImpl { internal readonly DeleteProvider> _deleteProvider; @@ -923,4 +1019,6 @@ SELECT "); } } #endregion + + #endregion } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 33789455..55a8f429 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1748,6 +1748,13 @@ + + + 设置表名 + + + + 动态Type,在使用 Update<object> 后使用本方法,指定实体类型 @@ -4681,6 +4688,22 @@ + + + 插入或更新数据字典,此功能依赖数据库特性(低版本可能不支持),参考如下: + MySql 5.6+: on duplicate key update + PostgreSQL 9.4+: on conflict do update + SqlServer 2008+: merge into + Oracle 11+: merge into + Sqlite: replace into + 达梦: merge into + 人大金仓:on conflict do update + 神通:merge into + MsAccess:不支持 + + + + 删除数据字典 Dictionary<string, object> diff --git a/FreeSql/Interface/Curd/IInsertOrUpdate.cs b/FreeSql/Interface/Curd/IInsertOrUpdate.cs index f2926980..c2cb1abb 100644 --- a/FreeSql/Interface/Curd/IInsertOrUpdate.cs +++ b/FreeSql/Interface/Curd/IInsertOrUpdate.cs @@ -69,6 +69,12 @@ namespace FreeSql /// IInsertOrUpdate AsTable(Func tableRule); /// + /// 设置表名 + /// + /// + /// + IInsertOrUpdate AsTable(string tableName); + /// /// 动态Type,在使用 Update<object> 后使用本方法,指定实体类型 /// /// diff --git a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs index 91968281..0c67b569 100644 --- a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs @@ -29,7 +29,7 @@ namespace FreeSql.Internal.CommonProvider public DbTransaction _transaction; public DbConnection _connection; public int _commandTimeout = 0; - public ColumnInfo IdentityColumn { get; } + public ColumnInfo IdentityColumn { get; private set; } public InsertOrUpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { @@ -37,12 +37,10 @@ namespace FreeSql.Internal.CommonProvider _commonUtils = commonUtils; _commonExpression = commonExpression; _table = _commonUtils.GetTableByEntity(typeof(T1)); - if (_table == null) - { + if (_table == null && typeof(T1) != typeof(Dictionary)) throw new Exception($"InsertOrUpdate<>的泛型参数 不支持 {typeof(T1)},请传递您的实体类"); - } if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); - IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault(); + IdentityColumn = _table?.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault(); } protected void ClearData() @@ -112,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider public IInsertOrUpdate SetSource(IEnumerable source) { if (source == null || source.Any() == false) return this; + UpdateProvider.GetDictionaryTableInfo(source.FirstOrDefault(), _orm, ref _table); AuditDataValue(this, source, _orm, _table, _auditValueChangedDict); _source.AddRange(source.Where(a => a != null)); return this; @@ -139,6 +138,11 @@ namespace FreeSql.Internal.CommonProvider _tableRule = tableRule; return this; } + public IInsertOrUpdate AsTable(string tableName) + { + _tableRule = (oldname) => tableName; + return this; + } public IInsertOrUpdate AsType(Type entityType) { if (entityType == typeof(object)) throw new Exception("IInsertOrUpdate.AsType 参数不支持指定为 object"); @@ -146,6 +150,7 @@ namespace FreeSql.Internal.CommonProvider var newtb = _commonUtils.GetTableByEntity(entityType); _table = newtb ?? throw new Exception("IInsertOrUpdate.AsType 参数错误,请传入正确的实体类型"); if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType); + IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault(); return this; }