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 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 moduleConditions = new List(); 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 GetSchemeTableColumns() { return new List { 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 GetSchemeControlTableColumns() { return new List { 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 GetCodeRecordTableColumns() { return new List { 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 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 mirrorColumns) { if (!TableExists(SchemeControlTableName)) return; HashSet keepColumns = new HashSet(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 GetTableColumnNames(string tableName) { List columns = new List(); 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 GetNumberRuleSchemeColumns() { return new List { 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 GetNumberRuleMirrorColumns() { List columns = new List(); 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); } } }