123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- using System.Collections.Generic;
- using System.Text;
- using System;
- using System.Linq;
- using System.Text.RegularExpressions;
- namespace JiaZhiQuan.Common.Utils.Extend {
- public static class BuildSqlExtensions {
- /// <summary>
- /// 生成更新sql
- /// </summary>
- /// <param name="source">数据</param>
- /// <param name="tableName">表名</param>
- /// <param name="uniqueFields">唯一字段,多个字段逗号隔开</param>
- /// <param name="cover">字段值为null时是否覆盖,默认覆盖</param>
- /// <returns></returns>
- /// <exception cref="Exception"></exception>
- public static string BuildBatchUpdatesql(this IEnumerable<object> source, string tableName,
- string uniqueFields, bool cover = true) {
- if (source.Count() == 0) return string.Empty;
- List<string> keyFields = uniqueFields?.Split(',').Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
- if (keyFields == null || keyFields.Count() == 0) throw new Exception("唯一字段列表不能为空");
- //考虑怎么写更优雅
- IEnumerable<IDictionary<string, object>> check = source.Where(x => x != null).Select(
- x => (IDictionary<string, object>)ExpandoUtils.ConvertToDynamic(x));
- foreach (var item in check) {
- foreach (var key in keyFields) {
- if (!item.ContainsKey(key)) throw new Exception("唯一字段不在数据字段中,不能创建更新sql");
- if (item[key] == null) throw new Exception("唯一字段对应的数据不能为空,不能创建更新sql");
- }
- }
- //根据唯一字段去重数据
- var data = check.Distinct(x => string.Join(",", keyFields.Select(y => x[y])));
- var fields = data.First().Keys;
- var cols = fields.Where(x => !keyFields.Contains(x));
- if (0 == cols.Count()) {
- return string.Empty;
- }
- StringBuilder sb = new StringBuilder("update ");
- sb.Append(tableName).Append(" t inner join ");
- sb.Append(BuildForeachStr(data, " union all ", t => {
- return BuildForeachStr(fields, ",",
- k => (null == t[k] ? "null" : "'" + EscapeSql(t[k]) + "'") + " " + k,
- "select ", null);
- }, "(", ")"));
- sb.Append(" a on ");
- sb.Append(BuildForeachStr(keyFields, " and ", t => $"t.{t}=a.{t}"));
- sb.Append(" set ");
- //是否覆盖
- if (cover) {
- sb.Append(BuildForeachStr(cols, ",", t => $"t.{t}=a.{t}"));
- } else {
- sb.Append(BuildForeachStr(cols, ",",
- t => $"t.{t}=case when a.{t} is null then t.{t} else a.{t} end"));
- }
- sb.Append(";select row_count();");
- return sb.ToString();
- }
- /// <summary>
- /// 生成插入sql,如果数据在库中存在,则去掉,并且会根据keyFields去重数据
- /// </summary>
- /// <param name="source">数据</param>
- /// <param name="tableName">表名</param>
- /// <param name="uniqueFields">唯一字段,多个字段逗号隔开</param>
- /// <returns></returns>
- /// <exception cref="Exception"></exception>
- public static string BuildBatchInsertsql(this IEnumerable<object> source, string tableName,
- string uniqueFields) {
- if (source.Count() == 0) return string.Empty;
- List<string> keyFields=uniqueFields?.Split(',').Where(x=>!string.IsNullOrWhiteSpace(x)).ToList();
- if (keyFields == null || keyFields.Count() == 0) throw new Exception("唯一字段列表不能为空");
- //考虑怎么写更优雅
- IEnumerable<IDictionary<string, object>> check = source.Where(x => x != null).Select(
- x => (IDictionary<string, object>)ExpandoUtils.ConvertToDynamic(x));
- foreach (var item in check) {
- foreach (var key in keyFields) {
- if (!item.ContainsKey(key)) throw new Exception("唯一字段不在数据字段中,不能创建插入sql");
- if (item[key] == null) throw new Exception("唯一字段对应的数据不能为空,不能创建插入sql");
- }
- }
- //根据唯一字段去重数据
- var data = check.Distinct(x => string.Join(",", keyFields.Select(y => x[y])));
- var fields = data.First().Keys;
- StringBuilder sb = new StringBuilder("insert into " + tableName);
- sb.Append(BuildForeachStr(fields, ",", open: "(", close: ")"));
- sb.Append(" select a.* from ").Append(BuildForeachStr(data, " union all ", t => {
- return BuildForeachStr(fields, ",",
- k => (null == t[k] ? "null" : "'" + EscapeSql(t[k]) + "'") + " " + k,
- "select ", null);
- }, "(", ")a "));
- sb.Append($" left join {tableName} t on ");
- sb.Append(BuildForeachStr(keyFields, " and ", t => $"t.{t}=a.{t} "));
- sb.Append($"where t.{keyFields.First()} is null ;select row_count();");
- return sb.ToString();
- }
- public static string BuildForeachStr<T>(this IEnumerable<T> list,
- string split, Func<T, string> getInfo = null, string open = null, string close = null) {
- if (list.Count() == 0) {
- return string.Empty;
- }
- StringBuilder sb = new StringBuilder(" ").Append(open ?? "");
- sb.Append(string.Join(split, list.Select(x => getInfo == null ? x.ToString() : getInfo(x))));
- sb.Append(close ?? "").Append(" ");
- return sb.ToString();
- }
- private static string EscapeSql(object value) {
- if (null == value) return null;
- if (value is DateTime time) return time.ToString("yyyy-MM-dd HH:mm:ss");
- else {
- return value.ToString().Replace(@"\", @"\\").Replace(@"'", @"\'");
- }
- }
- }
- }
|