Files
lserp_cs_6.0/插件库/Lskj.PubCodeDesign/CodeSchemeStorage.cs
T
2026-07-16 16:05:38 +08:00

887 lines
39 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Lskj.Business;
using Lskj.Business.Impl;
using Lskj.Control;
using Lskj.Core;
using Lskj.Util;
namespace Lskj.PubCodeDesign
{
internal static class CodeSchemeStorage
{
private const string SchemeTableName = "P_CodeSchemeTab";
private const string SchemeControlTableName = "P_CodeSchemeControlTab";
private const string CodeRecordTableName = "P_CodeSchemeRecordTab";
private const string CodeGenerateProcedureName = "P_create_CodeSchemeDocumentPr";
private const string NumberRuleTableName = "p_systemNumberRuleTab";
private const string DesignRuleUseColumn = "UseEd";
private const string DesignRuleSortColumn = "SortNo";
private const string DesignRuleFieldNameColumn = "FieldName";
private const string NumberRuleSchemeIdColumn = "SchemeId";
private const string NumberRuleSchemeCodeColumn = "SchemeCode";
private const string NumberRuleSchemeNameColumn = "SchemeName";
private const string NumberRuleMenuKeyColumn = "MenuKey";
private const string NumberRuleBindModuleColumn = "BindModule";
private const string NumberRuleBindModuleCodeColumn = "BindModuleCode";
private const string NumberRuleModIdColumn = "modid";
internal static void EnsureCodeSchemeStorage()
{
try
{
EnsureTable(SchemeTableName, GetCreateSchemeTableSql(), GetSchemeTableColumns());
EnsureTable(SchemeControlTableName, GetCreateSchemeControlTableSql(), GetSchemeControlTableColumns());
EnsureCodeRecordStorage();
DropIndexIfExists(SchemeControlTableName, "UX_CodeSchemeControl_Field");
DropIndexIfExists(SchemeControlTableName, "IX_CodeSchemeControl_Source");
DropIndexIfExists(SchemeTableName, "IX_CodeScheme_Menu");
DeleteDisabledCodeSchemes();
DropColumnIfExists(SchemeTableName, DesignRuleUseColumn);
RemoveLegacySchemeControlColumns();
EnsureIndex("UX_CodeScheme_Code", "CREATE UNIQUE INDEX UX_CodeScheme_Code ON P_CodeSchemeTab(SchemeCode)");
EnsureIndex("IX_CodeScheme_Menu", "CREATE INDEX IX_CodeScheme_Menu ON P_CodeSchemeTab(MenuKey)");
EnsureRuleStorage();
EnsureCodeGenerateProcedure();
EnsureIndexIfColumnsExist(SchemeControlTableName, new string[] { NumberRuleSchemeIdColumn, DesignRuleSortColumn }, "IX_CodeSchemeControl_Scheme", "CREATE INDEX IX_CodeSchemeControl_Scheme ON P_CodeSchemeControlTab(SchemeId, SortNo)");
EnsureIndexIfColumnsExist(SchemeControlTableName, new string[] { NumberRuleSchemeIdColumn, DesignRuleFieldNameColumn }, "IX_CodeSchemeControl_Field", "CREATE INDEX IX_CodeSchemeControl_Field ON P_CodeSchemeControlTab(SchemeId, FieldName)");
EnsureConstraint("FK_CodeSchemeControl_Scheme", "ALTER TABLE P_CodeSchemeControlTab ADD CONSTRAINT FK_CodeSchemeControl_Scheme FOREIGN KEY (SchemeId) REFERENCES P_CodeSchemeTab(SchemeId)");
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(ex);
MessageUtil.Show("编码方案表结构初始化失败:" + ex.Message);
}
}
private static void EnsureTable(string tableName, string createSql, List<TableColumnSpec> columns)
{
if (!TableExists(tableName))
{
SqlHelper.ExecuteNonQuery(createSql);
return;
}
foreach (TableColumnSpec column in columns)
{
if (!ColumnExists(tableName, column.Name))
{
SqlHelper.ExecuteNonQuery(string.Format("ALTER TABLE {0} ADD {1} {2}", tableName, column.Name, column.Definition));
}
}
}
private static void RemoveLegacySchemeControlColumns()
{
string[] legacyColumns =
{
"ControlType",
"FieldTypeId",
"ModuleCode",
"SourceType",
"SourceIndex",
"LabelText",
"UserName",
"ControlConfig",
"SchemeControlId",
"ControlWidth",
"ControlHeight",
DesignRuleUseColumn
};
foreach (string columnName in legacyColumns)
{
DropColumnIfExists(SchemeControlTableName, columnName);
}
}
private static void DeleteDisabledCodeSchemes()
{
if (!TableExists(SchemeTableName) || !ColumnExists(SchemeTableName, DesignRuleUseColumn)) return;
string sql = "SELECT SchemeId, BindModule, BindModuleCode FROM P_CodeSchemeTab WHERE ISNULL(UseEd, 1) = 0";
DataTable table = SqlHelper.ExecuteDataTable(sql);
if (table == null || table.Rows.Count == 0) return;
foreach (DataRow row in table.Rows)
{
int schemeId = ToInt(row["SchemeId"]);
string bindModuleCode = ToBool(row["BindModule"]) ? row["BindModuleCode"] + "" : string.Empty;
DeleteRuleRows(SchemeControlTableName, schemeId);
if (!string.IsNullOrWhiteSpace(bindModuleCode) && !BindModuleOwnedByEnabledScheme(bindModuleCode))
{
DeleteBindModuleNumberRuleRows(bindModuleCode);
}
string deleteSql = "DELETE FROM P_CodeSchemeTab WHERE SchemeId = @SchemeId";
SqlHelper.ExecuteNonQuery(CommandType.Text, deleteSql, new SqlParameter[] { new SqlParameter("@SchemeId", schemeId) });
}
}
private static bool BindModuleOwnedByEnabledScheme(string bindModuleCode)
{
if (string.IsNullOrWhiteSpace(bindModuleCode) || !TableExists(SchemeTableName) || !ColumnExists(SchemeTableName, DesignRuleUseColumn)) return false;
string sql = @"
SELECT COUNT(1)
FROM P_CodeSchemeTab
WHERE ISNULL(UseEd, 1) = 1
AND ISNULL(BindModule, 0) = 1
AND ISNULL(BindModuleCode, '') = @BindModuleCode";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@BindModuleCode", bindModuleCode) });
return ToInt(result) > 0;
}
private static void DeleteRuleRows(string tableName, int schemeId)
{
if (schemeId <= 0 || string.IsNullOrWhiteSpace(tableName) || !TableExists(tableName) || !ColumnExists(tableName, NumberRuleSchemeIdColumn)) return;
string sql = string.Format("DELETE FROM {0} WHERE {1} = @SchemeId", QuoteSqlIdentifier(tableName), QuoteSqlIdentifier(NumberRuleSchemeIdColumn));
SqlHelper.ExecuteNonQuery(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@SchemeId", schemeId) });
}
private static void DeleteBindModuleNumberRuleRows(string bindModuleCode)
{
if (string.IsNullOrWhiteSpace(bindModuleCode) || !TableExists(NumberRuleTableName)) return;
List<string> moduleConditions = new List<string>();
if (ColumnExists(NumberRuleTableName, NumberRuleModIdColumn))
{
moduleConditions.Add(string.Format("ISNULL(CONVERT(NVARCHAR(100), {0}), '') = @BindModuleCode", QuoteSqlIdentifier(NumberRuleModIdColumn)));
}
if (ColumnExists(NumberRuleTableName, NumberRuleBindModuleCodeColumn))
{
moduleConditions.Add(string.Format("ISNULL(CONVERT(NVARCHAR(100), {0}), '') = @BindModuleCode", QuoteSqlIdentifier(NumberRuleBindModuleCodeColumn)));
}
if (moduleConditions.Count == 0) return;
string sql = string.Format("DELETE FROM {0} WHERE ({1})", QuoteSqlIdentifier(NumberRuleTableName), string.Join(" OR ", moduleConditions.ToArray()));
SqlHelper.ExecuteNonQuery(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@BindModuleCode", bindModuleCode) });
}
internal static bool TableExists(string tableName)
{
string sql = "SELECT COUNT(1) FROM sysobjects WHERE id = OBJECT_ID(@TableName) AND xtype = 'U'";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@TableName", tableName) });
return Convert.ToInt32(result) > 0;
}
internal static bool ColumnExists(string tableName, string columnName)
{
string sql = "SELECT COUNT(1) FROM sys.columns WHERE object_id = OBJECT_ID(@TableName) AND name = @ColumnName";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[]
{
new SqlParameter("@TableName", tableName),
new SqlParameter("@ColumnName", columnName)
});
return Convert.ToInt32(result) > 0;
}
private static void EnsureIndex(string indexName, string createSql)
{
try
{
string sql = "SELECT COUNT(1) FROM sys.indexes WHERE name = @IndexName";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@IndexName", indexName) });
if (Convert.ToInt32(result) == 0)
{
SqlHelper.ExecuteNonQuery(createSql);
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(ex);
}
}
internal static void EnsureIndexIfColumnsExist(string tableName, string[] columnNames, string indexName, string createSql)
{
if (string.IsNullOrWhiteSpace(tableName) || columnNames == null) return;
foreach (string columnName in columnNames)
{
if (!ColumnExists(tableName, columnName)) return;
}
EnsureIndex(indexName, createSql);
}
private static void EnsureConstraint(string constraintName, string createSql)
{
try
{
string sql = "SELECT COUNT(1) FROM sys.objects WHERE name = @ConstraintName";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[] { new SqlParameter("@ConstraintName", constraintName) });
if (Convert.ToInt32(result) == 0)
{
SqlHelper.ExecuteNonQuery(createSql);
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(ex);
}
}
private static void DropIndexIfExists(string tableName, string indexName)
{
try
{
string sql = "SELECT COUNT(1) FROM sys.indexes WHERE object_id = OBJECT_ID(@TableName) AND name = @IndexName";
object result = SqlHelper.ExecuteScalar(CommandType.Text, sql, new SqlParameter[]
{
new SqlParameter("@TableName", tableName),
new SqlParameter("@IndexName", indexName)
});
if (Convert.ToInt32(result) == 0) return;
SqlHelper.ExecuteNonQuery(string.Format("DROP INDEX {0} ON {1}", QuoteSqlIdentifier(indexName), QuoteSqlIdentifier(tableName)));
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(ex);
}
}
private static void DropColumnIfExists(string tableName, string columnName)
{
try
{
if (!ColumnExists(tableName, columnName)) return;
DropColumnIndexes(tableName, columnName);
DropColumnDefaultConstraints(tableName, columnName);
SqlHelper.ExecuteNonQuery(string.Format("ALTER TABLE {0} DROP COLUMN {1}", QuoteSqlIdentifier(tableName), QuoteSqlIdentifier(columnName)));
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(ex);
}
}
private static void DropColumnIndexes(string tableName, string columnName)
{
string sql = @"
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql = @sql +
CASE
WHEN i.is_primary_key = 1 OR i.is_unique_constraint = 1 THEN
N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(i.object_id)) + N' DROP CONSTRAINT ' + QUOTENAME(i.name) + N';'
ELSE
N'DROP INDEX ' + QUOTENAME(i.name) + N' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(i.object_id)) + N';'
END
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE i.object_id = OBJECT_ID(@TableName)
AND c.name = @ColumnName
AND i.name IS NOT NULL;
IF LEN(@sql) > 0
BEGIN
EXEC sp_executesql @sql;
END";
SqlHelper.ExecuteNonQuery(CommandType.Text, sql, new SqlParameter[]
{
new SqlParameter("@TableName", tableName),
new SqlParameter("@ColumnName", columnName)
});
}
private static void DropColumnDefaultConstraints(string tableName, string columnName)
{
string sql = @"
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql = @sql + N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + N'.' + QUOTENAME(OBJECT_NAME(parent_object_id)) + N' DROP CONSTRAINT ' + QUOTENAME(name) + N';'
FROM sys.default_constraints
WHERE parent_object_id = OBJECT_ID(@TableName)
AND parent_column_id = COLUMNPROPERTY(OBJECT_ID(@TableName), @ColumnName, 'ColumnId');
IF LEN(@sql) > 0
BEGIN
EXEC sp_executesql @sql;
END";
SqlHelper.ExecuteNonQuery(CommandType.Text, sql, new SqlParameter[]
{
new SqlParameter("@TableName", tableName),
new SqlParameter("@ColumnName", columnName)
});
}
internal static string QuoteSqlIdentifier(string name)
{
return "[" + (name ?? string.Empty).Replace("]", "]]") + "]";
}
private static string GetCreateSchemeTableSql()
{
return @"CREATE TABLE P_CodeSchemeTab (
SchemeId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
SchemeCode VARCHAR(50) NOT NULL,
SchemeName NVARCHAR(100) NOT NULL,
MenuKey VARCHAR(200) NOT NULL,
SubSysId VARCHAR(50) NULL,
MenuId VARCHAR(50) NULL,
MenuStruct VARCHAR(50) NULL,
MenuCaption NVARCHAR(100) NULL,
ModuleCode VARCHAR(100) NOT NULL,
BindModule BIT NOT NULL DEFAULT(0),
BindSubSysId VARCHAR(50) NULL,
BindMenuStruct1 VARCHAR(50) NULL,
BindMenuStruct2 VARCHAR(50) NULL,
BindMenuId VARCHAR(50) NULL,
BindModuleCode VARCHAR(100) NULL,
IsDefault BIT NOT NULL DEFAULT(0),
Remark NVARCHAR(500) NULL,
CreateUserId VARCHAR(50) NULL,
CreateUserName NVARCHAR(50) NULL,
CreateTime DATETIME NOT NULL DEFAULT(GETDATE()),
ModifyUserId VARCHAR(50) NULL,
ModifyUserName NVARCHAR(50) NULL,
ModifyTime DATETIME NULL
)";
}
private static string GetCreateSchemeControlTableSql()
{
return @"CREATE TABLE P_CodeSchemeControlTab (
SchemeId INT NOT NULL DEFAULT(0),
SchemeCode VARCHAR(50) NOT NULL DEFAULT(''),
SchemeName NVARCHAR(100) NULL,
MenuKey VARCHAR(200) NULL,
BindModule BIT NOT NULL DEFAULT(0),
BindModuleCode VARCHAR(100) NULL,
modid VARCHAR(100) NULL
)";
}
private static List<TableColumnSpec> GetSchemeTableColumns()
{
return new List<TableColumnSpec>
{
new TableColumnSpec("SchemeId", "INT IDENTITY(1,1) NOT NULL"),
new TableColumnSpec("SchemeCode", "VARCHAR(50) NOT NULL DEFAULT('')"),
new TableColumnSpec("SchemeName", "NVARCHAR(100) NOT NULL DEFAULT('')"),
new TableColumnSpec("MenuKey", "VARCHAR(200) NOT NULL DEFAULT('')"),
new TableColumnSpec("SubSysId", "VARCHAR(50) NULL"),
new TableColumnSpec("MenuId", "VARCHAR(50) NULL"),
new TableColumnSpec("MenuStruct", "VARCHAR(50) NULL"),
new TableColumnSpec("MenuCaption", "NVARCHAR(100) NULL"),
new TableColumnSpec("ModuleCode", "VARCHAR(100) NOT NULL DEFAULT('')"),
new TableColumnSpec("BindModule", "BIT NOT NULL DEFAULT(0)"),
new TableColumnSpec("BindSubSysId", "VARCHAR(50) NULL"),
new TableColumnSpec("BindMenuStruct1", "VARCHAR(50) NULL"),
new TableColumnSpec("BindMenuStruct2", "VARCHAR(50) NULL"),
new TableColumnSpec("BindMenuId", "VARCHAR(50) NULL"),
new TableColumnSpec("BindModuleCode", "VARCHAR(100) NULL"),
new TableColumnSpec("IsDefault", "BIT NOT NULL DEFAULT(0)"),
new TableColumnSpec("Remark", "NVARCHAR(500) NULL"),
new TableColumnSpec("CreateUserId", "VARCHAR(50) NULL"),
new TableColumnSpec("CreateUserName", "NVARCHAR(50) NULL"),
new TableColumnSpec("CreateTime", "DATETIME NOT NULL DEFAULT(GETDATE())"),
new TableColumnSpec("ModifyUserId", "VARCHAR(50) NULL"),
new TableColumnSpec("ModifyUserName", "NVARCHAR(50) NULL"),
new TableColumnSpec("ModifyTime", "DATETIME NULL")
};
}
private static List<TableColumnSpec> GetSchemeControlTableColumns()
{
return new List<TableColumnSpec>
{
new TableColumnSpec("SchemeId", "INT NOT NULL DEFAULT(0)"),
new TableColumnSpec("SchemeCode", "VARCHAR(50) NOT NULL DEFAULT('')"),
new TableColumnSpec("SchemeName", "NVARCHAR(100) NULL"),
new TableColumnSpec("MenuKey", "VARCHAR(200) NULL"),
new TableColumnSpec("BindModule", "BIT NOT NULL DEFAULT(0)"),
new TableColumnSpec("BindModuleCode", "VARCHAR(100) NULL"),
new TableColumnSpec("modid", "VARCHAR(100) NULL")
};
}
private static string GetCreateCodeRecordTableSql()
{
return @"CREATE TABLE P_CodeSchemeRecordTab (
RecordId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
SchemeId INT NOT NULL DEFAULT(0),
SchemeCode VARCHAR(50) NOT NULL DEFAULT(''),
SchemeName NVARCHAR(100) NULL,
MenuKey VARCHAR(200) NULL,
SequenceKey NVARCHAR(300) NOT NULL DEFAULT(''),
SerialNo INT NOT NULL DEFAULT(0),
CodeValue NVARCHAR(300) NOT NULL,
RuleText NVARCHAR(MAX) NULL,
CreateUserId VARCHAR(50) NULL,
CreateUserName NVARCHAR(50) NULL,
CreateTime DATETIME NOT NULL DEFAULT(GETDATE())
)";
}
private static List<TableColumnSpec> GetCodeRecordTableColumns()
{
return new List<TableColumnSpec>
{
new TableColumnSpec("RecordId", "INT IDENTITY(1,1) NOT NULL"),
new TableColumnSpec("SchemeId", "INT NOT NULL DEFAULT(0)"),
new TableColumnSpec("SchemeCode", "VARCHAR(50) NOT NULL DEFAULT('')"),
new TableColumnSpec("SchemeName", "NVARCHAR(100) NULL"),
new TableColumnSpec("MenuKey", "VARCHAR(200) NULL"),
new TableColumnSpec("SequenceKey", "NVARCHAR(300) NOT NULL DEFAULT('')"),
new TableColumnSpec("SerialNo", "INT NOT NULL DEFAULT(0)"),
new TableColumnSpec("CodeValue", "NVARCHAR(300) NOT NULL DEFAULT('')"),
new TableColumnSpec("RuleText", "NVARCHAR(MAX) NULL"),
new TableColumnSpec("CreateUserId", "VARCHAR(50) NULL"),
new TableColumnSpec("CreateUserName", "NVARCHAR(50) NULL"),
new TableColumnSpec("CreateTime", "DATETIME NOT NULL DEFAULT(GETDATE())")
};
}
internal static void EnsureCodeRecordStorage()
{
EnsureTable(CodeRecordTableName, GetCreateCodeRecordTableSql(), GetCodeRecordTableColumns());
EnsureIndexIfColumnsExist(CodeRecordTableName, new string[] { "SchemeId", "CodeValue" }, "UX_CodeSchemeRecord_Code", "CREATE UNIQUE INDEX UX_CodeSchemeRecord_Code ON P_CodeSchemeRecordTab(SchemeId, CodeValue)");
EnsureIndexIfColumnsExist(CodeRecordTableName, new string[] { "SchemeId", "SequenceKey", "SerialNo" }, "IX_CodeSchemeRecord_Sequence", "CREATE INDEX IX_CodeSchemeRecord_Sequence ON P_CodeSchemeRecordTab(SchemeId, SequenceKey, SerialNo)");
}
internal static void EnsureCodeGenerateProcedure()
{
string createSql = string.Format(@"
IF OBJECT_ID(N'dbo.{0}', N'P') IS NULL
BEGIN
EXEC(N'CREATE PROCEDURE dbo.{0} AS BEGIN SET NOCOUNT ON; END')
END", CodeGenerateProcedureName);
SqlHelper.ExecuteNonQuery(CommandType.Text, createSql);
SqlHelper.ExecuteNonQuery(CommandType.Text, GetAlterCodeGenerateProcedureSql());
}
private static string GetAlterCodeGenerateProcedureSql()
{
return string.Format(@"
ALTER PROCEDURE dbo.{0}
@SchemeId INT,
@CreateUserId VARCHAR(50) = '',
@CreateUserName NVARCHAR(50) = '',
@return_id NVARCHAR(300) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SchemeCode VARCHAR(50);
DECLARE @SchemeName NVARCHAR(100);
DECLARE @MenuKey VARCHAR(200);
DECLARE @BindModule BIT;
SELECT
@SchemeCode = ISNULL(SchemeCode, ''),
@SchemeName = ISNULL(SchemeName, N''),
@MenuKey = ISNULL(MenuKey, ''),
@BindModule = ISNULL(BindModule, 0)
FROM P_CodeSchemeTab
WHERE SchemeId = @SchemeId;
IF @SchemeCode IS NULL
BEGIN
RAISERROR(N'未找到编码方案。', 16, 1);
RETURN;
END
IF ISNULL(@BindModule, 0) = 1
BEGIN
RAISERROR(N'当前方案已绑定模块,view模式只支持未绑定方案生成编码。', 16, 1);
RETURN;
END
DECLARE @defaultValue VARCHAR(MAX),
@defaultSql NVARCHAR(MAX),
@likeValue VARCHAR(MAX),
@likeSql NVARCHAR(MAX),
@prefixSql NVARCHAR(MAX),
@likePrefix VARCHAR(300),
@orderlen INT,
@emptyint INT,
@orderNumber VARCHAR(300),
@out_char VARCHAR(300),
@tmpSql NVARCHAR(MAX),
@tmpvar VARCHAR(100),
@avalue VARCHAR(300),
@RuleText NVARCHAR(MAX),
@SerialNo INT;
BEGIN TRY
SELECT CASE WHEN element=1 THEN QUOTENAME(RIGHT('0000000000'+ISNULL(LTRIM(defaultvalue),''),elementlen),'''')
WHEN element=2 THEN 'CONVERT(varchar(4),'+defaultvalue+',120)'
WHEN element=3 THEN 'RIGHT(CONVERT(varchar(4),'+defaultvalue+',120),2)'
WHEN element=4 THEN 'RIGHT('+QUOTENAME('00','''')+'+cast(month('+defaultvalue+') as varchar),2)'
WHEN element=5 THEN 'RIGHT('+QUOTENAME('00','''')+'+cast(day('+defaultvalue+') as varchar),2)'
WHEN element=6 AND ISNULL(elementlen,0)>0 THEN 'RIGHT('+QUOTENAME('000000000000','''')+'+'+defaultvalue+','+CAST(elementlen AS varchar)+')'
WHEN element=6 AND ISNULL(elementlen,0)=0 THEN defaultvalue
WHEN element=999 THEN QUOTENAME(CASE WHEN ISNULL(LTRIM(defaultvalue),'')='' THEN '0000000000000001' ELSE defaultvalue END,'''')
ELSE 'RIGHT('+QUOTENAME('000000000000','''')+'+'+defaultvalue+','+CAST(elementlen AS varchar)+')'
END AS defaultvalue,
ISNULL(splitchar,'') AS splitchar,
CASE WHEN element=1 AND isrelated=1 THEN QUOTENAME(RIGHT('0000000000'+ISNULL(LTRIM(defaultvalue),''),elementlen),'''')
WHEN element=2 AND isrelated=1 THEN 'CONVERT(varchar(4),'+defaultvalue+',120)'
WHEN element=3 AND isrelated=1 THEN 'RIGHT(CONVERT(varchar(4),'+defaultvalue+',120),2)'
WHEN element=4 AND isrelated=1 THEN 'RIGHT('+QUOTENAME('00','''')+'+cast(month('+defaultvalue+') as varchar),2)'
WHEN element=5 AND isrelated=1 THEN 'RIGHT('+QUOTENAME('00','''')+'+cast(day('+defaultvalue+') as varchar),2)'
WHEN element=6 AND isrelated=1 AND ISNULL(elementlen,0)>0 THEN 'RIGHT(''000000000000''+'+defaultvalue+','+CAST(elementlen AS varchar)+')'
WHEN element=6 AND isrelated=1 AND ISNULL(elementlen,0)=0 THEN defaultvalue
WHEN element=999 THEN ''
WHEN isrelated=0 THEN QUOTENAME(RIGHT('__________',elementlen),'''')
ELSE ''
END AS likevalue,
CASE WHEN element=999 THEN elementlen ELSE 0 END AS orderlen
INTO #tempordernumber
FROM (
SELECT
CASE WHEN ISNUMERIC(CONVERT(VARCHAR(20), element)) = 1 THEN CONVERT(INT, element) ELSE 0 END AS element,
ISNULL(CONVERT(VARCHAR(MAX), defaultvalue), '') AS defaultvalue,
ISNULL(CONVERT(VARCHAR(50), splitchar), '') AS splitchar,
CASE WHEN ISNUMERIC(CONVERT(VARCHAR(20), elementlen)) = 1 THEN CONVERT(INT, elementlen) ELSE 0 END AS elementlen,
CASE WHEN ISNULL(CONVERT(VARCHAR(20), isrelated), '0') IN ('1', 'True', 'true', '是') THEN 1 ELSE 0 END AS isrelated,
CASE WHEN ISNUMERIC(CONVERT(VARCHAR(20), Orderid)) = 1 THEN CONVERT(INT, Orderid) ELSE 0 END AS Orderid,
CASE WHEN ISNUMERIC(CONVERT(VARCHAR(20), ID)) = 1 THEN CONVERT(INT, ID) ELSE 0 END AS ID
FROM P_CodeSchemeControlTab
WHERE SchemeId=@SchemeId
AND ISNULL(CONVERT(NVARCHAR(20), enableFlag), N'1') IN (N'1', N'True', N'true', N'是')
) ruleSource
ORDER BY Orderid, ID;
SET @defaultValue='';
SET @defaultSql='';
SET @likeValue='';
SET @likeSql='';
SET @prefixSql='';
SET @likePrefix='';
SET @orderlen=0;
SET @emptyint=0;
SET @orderNumber='';
SET @out_char='';
SET @tmpvar='';
SET @avalue='';
SET @SerialNo=0;
SELECT @emptyint=1,
@defaultValue=@defaultValue+defaultvalue+'+'+QUOTENAME(splitchar,'''')+'+',
@likeValue=@likeValue+CASE WHEN likevalue='' THEN '' ELSE likevalue+'+'+QUOTENAME(splitchar,'''')+'+' END,
@orderlen=@orderlen+orderlen
FROM #tempordernumber;
SET @defaultValue=REPLACE(@defaultValue,'{{&loginid&}}',CAST(ISNULL(@CreateUserId,'') AS VARCHAR));
SET @likeValue=REPLACE(@likeValue,'{{&loginid&}}',CAST(ISNULL(@CreateUserId,'') AS VARCHAR));
IF ISNULL(@emptyint,0)=0
BEGIN
SET @defaultSql='select @out_char=replace(convert(varchar(10),getdate(),120),''-'','''')+''0001''';
SET @likeSql='select @out_char=max(CodeValue) from P_CodeSchemeRecordTab with(updlock,holdlock) where SchemeId=@SchemeId and CodeValue like '+QUOTENAME(REPLACE(CONVERT(VARCHAR(10),GETDATE(),120),'-','')+'%','''');
SET @prefixSql='select @out_char='+QUOTENAME(REPLACE(CONVERT(VARCHAR(10),GETDATE(),120),'-',''),'''');
SET @orderlen=4;
END
ELSE
BEGIN
IF ISNULL(@orderlen,0)<=0
BEGIN
RAISERROR(N'当前方案未配置流水号规则。', 16, 1);
RETURN;
END
IF ISNULL(@defaultValue,'')<>''
SET @defaultSql='select @out_char='+LEFT(@defaultValue,LEN(@defaultValue)-1);
IF ISNULL(@likeValue,'')<>''
BEGIN
SET @likeSql='select @out_char=max(CodeValue) from P_CodeSchemeRecordTab with(updlock,holdlock) where SchemeId=@SchemeId and CodeValue like '+@likeValue+QUOTENAME('%','''');
SET @prefixSql='select @out_char='+LEFT(@likeValue,LEN(@likeValue)-1);
END
ELSE
BEGIN
SET @likeSql='select @out_char=max(CodeValue) from P_CodeSchemeRecordTab with(updlock,holdlock) where SchemeId=@SchemeId';
SET @prefixSql='select @out_char=''''';
END
END
WHILE CHARINDEX('{{&',@defaultSql)>0
BEGIN
IF CHARINDEX('&}}',@defaultSql)<1
BEGIN
RAISERROR(N'变量名缺少&}}号。', 16, 1);
RETURN;
END
SET @tmpvar=SUBSTRING(@defaultSql,CHARINDEX('{{&',@defaultSql),CHARINDEX('&}}',@defaultSql)-CHARINDEX('{{&',@defaultSql)+2);
RAISERROR(N'未绑定模块方案不支持字段变量:%s。', 16, 1, @tmpvar);
RETURN;
END
WHILE CHARINDEX('{{&',@likeSql)>0
BEGIN
IF CHARINDEX('&}}',@likeSql)<1
BEGIN
RAISERROR(N'变量名缺少&}}号。', 16, 1);
RETURN;
END
SET @tmpvar=SUBSTRING(@likeSql,CHARINDEX('{{&',@likeSql),CHARINDEX('&}}',@likeSql)-CHARINDEX('{{&',@likeSql)+2);
RAISERROR(N'未绑定模块方案不支持字段变量:%s。', 16, 1, @tmpvar);
RETURN;
END
SET @RuleText=ISNULL(@defaultSql,N'')+CHAR(13)+CHAR(10)+ISNULL(@likeSql,N'');
BEGIN TRANSACTION;
SET @out_char='';
IF ISNULL(@likeSql,'')<>''
EXEC sp_executesql @likeSql,N'@SchemeId int,@out_char varchar(300) output', @SchemeId, @out_char output;
IF ISNULL(LTRIM(@out_char),'')<>''
BEGIN
SET @orderNumber=LEFT(@out_char, LEN(@out_char)-@orderlen)+
RIGHT('0000000000'+CAST(CAST(RIGHT(@out_char,@orderlen) AS INT)+1 AS VARCHAR),@orderlen);
END
ELSE
BEGIN
EXEC sp_executesql @defaultSql,N'@out_char varchar(300) output', @out_char output;
SET @orderNumber=ISNULL(LTRIM(@out_char),'');
END
SET @out_char='';
IF ISNULL(@prefixSql,'')<>''
BEGIN
EXEC sp_executesql @prefixSql,N'@out_char varchar(300) output', @out_char output;
SET @likePrefix=ISNULL(@out_char,'');
END
IF LEN(ISNULL(@orderNumber,''))=0
RAISERROR(N'生成编码为空,请检查方案规则。', 16, 1);
IF LEN(@orderNumber)>300
RAISERROR(N'生成编码长度超过300,请检查方案规则。', 16, 1);
IF EXISTS (SELECT 1 FROM P_CodeSchemeRecordTab WITH (UPDLOCK, HOLDLOCK) WHERE SchemeId=@SchemeId AND CodeValue=@orderNumber)
RAISERROR(N'生成编码重复,请检查方案规则。', 16, 1);
IF ISNUMERIC(RIGHT(@orderNumber,@orderlen))=1
SET @SerialNo=CONVERT(INT,RIGHT(@orderNumber,@orderlen));
INSERT INTO P_CodeSchemeRecordTab
(SchemeId, SchemeCode, SchemeName, MenuKey, SequenceKey, SerialNo, CodeValue, RuleText, CreateUserId, CreateUserName, CreateTime)
VALUES
(@SchemeId, @SchemeCode, @SchemeName, @MenuKey, ISNULL(@likePrefix,''), @SerialNo, @orderNumber, @RuleText, @CreateUserId, @CreateUserName, GETDATE());
SET @return_id=@orderNumber;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
DECLARE @ErrorMessage NVARCHAR(4000);
SET @ErrorMessage = ERROR_MESSAGE();
RAISERROR(@ErrorMessage, 16, 1);
END CATCH
END", CodeGenerateProcedureName);
}
internal static void EnsureRuleStorage()
{
EnsureSchemeControlRuleStorage();
}
private static void EnsureNumberRuleSchemeStorage()
{
}
private static void EnsureSchemeControlRuleStorage()
{
if (!TableExists(SchemeControlTableName)) return;
foreach (TableColumnSpec column in GetNumberRuleSchemeColumns())
{
if (!ColumnExists(SchemeControlTableName, column.Name))
{
SqlHelper.ExecuteNonQuery(string.Format("ALTER TABLE {0} ADD {1} {2}", QuoteSqlIdentifier(SchemeControlTableName), QuoteSqlIdentifier(column.Name), column.Definition));
}
}
if (TableExists(NumberRuleTableName))
{
List<TableColumnSpec> mirrorColumns = GetNumberRuleMirrorColumns();
foreach (TableColumnSpec column in mirrorColumns)
{
if (!ColumnExists(SchemeControlTableName, column.Name))
{
SqlHelper.ExecuteNonQuery(string.Format("ALTER TABLE {0} ADD {1} {2}", QuoteSqlIdentifier(SchemeControlTableName), QuoteSqlIdentifier(column.Name), column.Definition));
}
}
RemoveSchemeControlUnusedRuleColumns(mirrorColumns);
}
EnsureIndex("IX_CodeSchemeControl_Menu", "CREATE INDEX IX_CodeSchemeControl_Menu ON P_CodeSchemeControlTab(MenuKey, SchemeId)");
}
private static void RemoveSchemeControlUnusedRuleColumns(List<TableColumnSpec> mirrorColumns)
{
if (!TableExists(SchemeControlTableName)) return;
HashSet<string> keepColumns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (TableColumnSpec column in GetNumberRuleSchemeColumns())
{
keepColumns.Add(column.Name);
}
if (mirrorColumns != null)
{
foreach (TableColumnSpec column in mirrorColumns)
{
keepColumns.Add(column.Name);
}
}
foreach (string columnName in GetTableColumnNames(SchemeControlTableName))
{
if (keepColumns.Contains(columnName)) continue;
DropColumnIfExists(SchemeControlTableName, columnName);
}
}
private static List<string> GetTableColumnNames(string tableName)
{
List<string> columns = new List<string>();
if (string.IsNullOrWhiteSpace(tableName) || !TableExists(tableName)) return columns;
string sql = @"SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(@TableName) ORDER BY column_id";
DataTable table = SqlHelper.ExecuteDataTable(sql, new SqlParameter[] { new SqlParameter("@TableName", tableName) });
if (table == null) return columns;
foreach (DataRow row in table.Rows)
{
string columnName = row["name"] + "";
if (!string.IsNullOrWhiteSpace(columnName))
{
columns.Add(columnName);
}
}
return columns;
}
private static List<TableColumnSpec> GetNumberRuleSchemeColumns()
{
return new List<TableColumnSpec>
{
new TableColumnSpec(NumberRuleSchemeIdColumn, "INT NOT NULL DEFAULT(0)"),
new TableColumnSpec(NumberRuleSchemeCodeColumn, "VARCHAR(50) NOT NULL DEFAULT('')"),
new TableColumnSpec(NumberRuleSchemeNameColumn, "NVARCHAR(100) NULL"),
new TableColumnSpec(NumberRuleMenuKeyColumn, "VARCHAR(200) NULL"),
new TableColumnSpec(NumberRuleBindModuleColumn, "BIT NOT NULL DEFAULT(0)"),
new TableColumnSpec(NumberRuleBindModuleCodeColumn, "VARCHAR(100) NULL"),
new TableColumnSpec(NumberRuleModIdColumn, "VARCHAR(100) NULL")
};
}
private static List<TableColumnSpec> GetNumberRuleMirrorColumns()
{
List<TableColumnSpec> columns = new List<TableColumnSpec>();
string sql = @"
SELECT
c.COLUMN_NAME,
c.DATA_TYPE,
c.CHARACTER_MAXIMUM_LENGTH,
c.NUMERIC_PRECISION,
c.NUMERIC_SCALE,
COLUMNPROPERTY(OBJECT_ID(c.TABLE_SCHEMA + '.' + c.TABLE_NAME), c.COLUMN_NAME, 'IsComputed') AS IsComputed
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = @TableName
ORDER BY c.ORDINAL_POSITION";
DataTable table = SqlHelper.ExecuteDataTable(sql, new SqlParameter[] { new SqlParameter("@TableName", NumberRuleTableName) });
if (table == null) return columns;
foreach (DataRow row in table.Rows)
{
string columnName = row["COLUMN_NAME"] + "";
if (string.IsNullOrWhiteSpace(columnName)) continue;
if (string.Equals(columnName, DesignRuleUseColumn, StringComparison.OrdinalIgnoreCase)) continue;
if (ToInt(row["IsComputed"]) == 1) continue;
string definition = GetColumnDefinitionFromSchemaRow(row);
if (string.IsNullOrWhiteSpace(definition)) continue;
columns.Add(new TableColumnSpec(columnName, definition));
}
return columns;
}
private static string GetColumnDefinitionFromSchemaRow(DataRow row)
{
string dataType = (row["DATA_TYPE"] + "").Trim();
if (string.IsNullOrWhiteSpace(dataType)) return string.Empty;
if (string.Equals(dataType, "timestamp", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "rowversion", StringComparison.OrdinalIgnoreCase))
{
return string.Empty;
}
string typeText = dataType;
int maxLength = ToInt(row["CHARACTER_MAXIMUM_LENGTH"]);
if (IsLengthColumnType(dataType))
{
typeText += maxLength < 0 ? "(MAX)" : "(" + maxLength + ")";
}
else if (IsPrecisionColumnType(dataType))
{
int precision = ToInt(row["NUMERIC_PRECISION"]);
int scale = ToInt(row["NUMERIC_SCALE"]);
if (precision > 0)
{
typeText += "(" + precision + "," + Math.Max(0, scale) + ")";
}
}
else if (IsDateTimePrecisionColumnType(dataType))
{
int scale = ToInt(row["NUMERIC_SCALE"]);
if (scale > 0)
{
typeText += "(" + scale + ")";
}
}
return typeText + " NULL";
}
private static int ToInt(object value)
{
int result;
return int.TryParse(value + "", out result) ? result : 0;
}
private static bool ToBool(object value)
{
if (value == null || value == DBNull.Value) return false;
bool boolValue;
if (bool.TryParse(value + "", out boolValue)) return boolValue;
return ToInt(value) != 0;
}
private static bool IsLengthColumnType(string dataType)
{
return string.Equals(dataType, "varchar", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "nvarchar", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "char", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "nchar", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "varbinary", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "binary", StringComparison.OrdinalIgnoreCase);
}
private static bool IsPrecisionColumnType(string dataType)
{
return string.Equals(dataType, "decimal", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "numeric", StringComparison.OrdinalIgnoreCase);
}
private static bool IsDateTimePrecisionColumnType(string dataType)
{
return string.Equals(dataType, "datetime2", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "datetimeoffset", StringComparison.OrdinalIgnoreCase) ||
string.Equals(dataType, "time", StringComparison.OrdinalIgnoreCase);
}
}
}