Initial_commit_SecMPS_v2
This commit is contained in:
206
api_sqlsugar/VolPro.Core/Extensions/IdentitySqlCode.cs
Normal file
206
api_sqlsugar/VolPro.Core/Extensions/IdentitySqlCode.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using VolPro.Core.Configuration;
|
||||
using VolPro.Core.Const;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.Enums;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Core.UserManager;
|
||||
|
||||
namespace VolPro.Core.Extensions
|
||||
{
|
||||
public static class IdentitySqlCode
|
||||
{
|
||||
public static void CreateCode(
|
||||
Dictionary<string, object> mainData,
|
||||
string tableName,
|
||||
List<TableColumnField> tableColumns = null,
|
||||
string leftQuote = null,
|
||||
string rightQuote = null)
|
||||
{
|
||||
// 1) 读取编码规则
|
||||
var query = IdentityCode.CodeRules.Where(x =>
|
||||
!string.IsNullOrEmpty(x.TableName) &&
|
||||
x.TableName.Equals(tableName, StringComparison.OrdinalIgnoreCase));
|
||||
if (AppSetting.UseDynamicShareDB)
|
||||
{
|
||||
query = query.Where(x => x.DbServiceId == UserContext.CurrentServiceId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AppSetting.TenancyField != null)
|
||||
{
|
||||
query = query.Where(x => x.TenancyId == UserContext.CurrentServiceId.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
var rule = query.OrderByDescending(x => x.CreateDate).FirstOrDefault();
|
||||
if (rule == null) return;
|
||||
|
||||
RuleIncremental ruleIncremental = RuleIncremental.day;
|
||||
try
|
||||
{
|
||||
ruleIncremental = (RuleIncremental)Enum.Parse(typeof(RuleIncremental), rule.RuleIncremental);
|
||||
}
|
||||
catch
|
||||
{
|
||||
ruleIncremental = RuleIncremental.day;
|
||||
}
|
||||
|
||||
// 2) 映射单据字段(rule.Field 可能大小写/别名与实际列名不一致)
|
||||
string codeFieldName = rule.Field;
|
||||
if (tableColumns != null && !string.IsNullOrEmpty(codeFieldName))
|
||||
{
|
||||
var col = tableColumns.FirstOrDefault(c =>
|
||||
c.ColumnName.Equals(codeFieldName, StringComparison.OrdinalIgnoreCase));
|
||||
if (col != null) codeFieldName = col.ColumnName;
|
||||
}
|
||||
if (string.IsNullOrEmpty(codeFieldName)) return;
|
||||
|
||||
// 3) 找到业务表真实表名与库
|
||||
var tableInfo = TableColumnContext.TableInfo.FirstOrDefault(x =>
|
||||
!string.IsNullOrEmpty(x.TableName) &&
|
||||
x.TableName.Equals(tableName, StringComparison.OrdinalIgnoreCase));
|
||||
if (tableInfo == null) return;
|
||||
|
||||
string dbTableName = string.IsNullOrEmpty(tableInfo.TableTrueName)
|
||||
? tableInfo.TableName
|
||||
: tableInfo.TableTrueName;
|
||||
|
||||
string dbService = tableInfo.DBServer;
|
||||
if (string.IsNullOrEmpty(dbService)) return;
|
||||
|
||||
// 4) 构造规则前缀与日期起点
|
||||
string preCode = rule.PrefixCode ?? "";
|
||||
string concatenationSymbol = rule.ConcatenationSymbol ?? "";
|
||||
string dateFormat = rule.RuleType;
|
||||
if (dateFormat == RuleIncremental.none.ToString())
|
||||
{
|
||||
dateFormat = null;
|
||||
}
|
||||
|
||||
DateTime? dateNow = null;
|
||||
switch (ruleIncremental)
|
||||
{
|
||||
case RuleIncremental.day:
|
||||
dateNow = (DateTime)DateTime.Now.ToString("yyyy-MM-dd").GetDateTime();
|
||||
break;
|
||||
case RuleIncremental.month:
|
||||
dateNow = (DateTime)DateTime.Now.ToString("yyyy-MM-01").GetDateTime();
|
||||
break;
|
||||
case RuleIncremental.year:
|
||||
dateNow = (DateTime)DateTime.Now.ToString("yyyy-01-01").GetDateTime();
|
||||
break;
|
||||
case RuleIncremental.none:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
string dateText = dateNow?.ToString("yyyy-MM-dd") ?? "none";
|
||||
|
||||
string dateFieldName =
|
||||
!string.IsNullOrWhiteSpace(rule.OrderFiled)
|
||||
? rule.OrderFiled
|
||||
: AppSetting.CreateMember.DateField;
|
||||
|
||||
// 5) 共享缓存key(与 IdentityCode.CreateList 保持同形态,避免并发重复)
|
||||
string serviceId = "";
|
||||
if (AppSetting.UseDynamicShareDB || !string.IsNullOrEmpty(AppSetting.TenancyField))
|
||||
{
|
||||
serviceId = $"_{UserContext.CurrentServiceId}";
|
||||
}
|
||||
string cacheKey = $"{tableName}_{ruleIncremental}_{dateText}{serviceId}";
|
||||
|
||||
// 6) 自增流水号:同一 cacheKey 下,保证并发安全
|
||||
int number = IdentityCode._counters.AddOrUpdate(
|
||||
cacheKey,
|
||||
addValueFactory: (k) =>
|
||||
{
|
||||
// 获取库类型决定左右引号(MySql: ``, SqlServer: [ ])
|
||||
string dbType = DbRelativeCache.GetDbType(dbService) ?? DBType.Name;
|
||||
DbCurrentType dbCurrentType = (DbCurrentType)Enum.Parse(typeof(DbCurrentType), dbType, true);
|
||||
int last = GetLastIncrementBySql(
|
||||
dbService,
|
||||
dbTableName,
|
||||
codeFieldName,
|
||||
preCode,
|
||||
dateFieldName,
|
||||
dateNow,
|
||||
rule.ValueLen,
|
||||
leftQuote,
|
||||
rightQuote);
|
||||
return last + 1;
|
||||
},
|
||||
updateValueFactory: (k, existingValue) => existingValue + 1);
|
||||
|
||||
// 7) 生成最终编码字符串
|
||||
string ruleText = dateFormat == null
|
||||
? preCode
|
||||
: $"{preCode}{concatenationSymbol}{DateTime.Now.ToString(dateFormat)}";
|
||||
|
||||
string code = $"{ruleText}{concatenationSymbol}{(number).ToString("D" + rule.ValueLen)}";
|
||||
mainData[codeFieldName] = code;
|
||||
}
|
||||
|
||||
private static int GetLastIncrementBySql(
|
||||
string dbService,
|
||||
string dbTableName,
|
||||
string codeFieldName,
|
||||
string preCode,
|
||||
string dateFieldName,
|
||||
DateTime? dateNow,
|
||||
int len,
|
||||
string leftQuote,
|
||||
string rightQuote)
|
||||
{
|
||||
string table = $"{leftQuote}{dbTableName}{rightQuote}";
|
||||
string codeField = $"{leftQuote}{codeFieldName}{rightQuote}";
|
||||
string dateField = string.IsNullOrWhiteSpace(dateFieldName)
|
||||
? null
|
||||
: $"{leftQuote}{dateFieldName}{rightQuote}";
|
||||
|
||||
string sqlWhere = $"{codeField} LIKE @preCodeLike";
|
||||
if (dateNow != null && !string.IsNullOrEmpty(dateField))
|
||||
{
|
||||
sqlWhere += $" AND {dateField} >= @dateNow";
|
||||
}
|
||||
|
||||
// 取最后一条:按 codeField 倒序取 1 条
|
||||
// 这里不再通过 leftQuote/rightQuote 推断 DB 类型,所以按 dbService 取一次 DB 类型决定 SQL 语法
|
||||
string dbType = DbRelativeCache.GetDbType(dbService) ?? DBType.Name;
|
||||
DbCurrentType dbCurrentType = (DbCurrentType)Enum.Parse(typeof(DbCurrentType), dbType, true);
|
||||
|
||||
string sql;
|
||||
if (dbCurrentType == DbCurrentType.MsSql)
|
||||
{
|
||||
sql = $"SELECT TOP 1 {codeField} FROM {table} WHERE {sqlWhere} ORDER BY {codeField} DESC";
|
||||
}
|
||||
else if (dbCurrentType == DbCurrentType.Oracle)
|
||||
{
|
||||
sql = $"SELECT {codeField} FROM {table} WHERE {sqlWhere} ORDER BY {codeField} DESC FETCH FIRST 1 ROWS ONLY";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = $"SELECT {codeField} FROM {table} WHERE {sqlWhere} ORDER BY {codeField} DESC LIMIT 1";
|
||||
}
|
||||
|
||||
var dapper = DbSqlSugar.DbManger.GetConnection(dbService);
|
||||
string lastCode = dapper.Ado.SqlQuery<string>(sql, new
|
||||
{
|
||||
preCodeLike = $"{preCode}%",
|
||||
dateNow
|
||||
}).FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrEmpty(lastCode)) return 0;
|
||||
|
||||
if (lastCode.Length >= len)
|
||||
{
|
||||
return int.TryParse(lastCode.Substring(lastCode.Length - len), out var n) ? n : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user