65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL 框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (22投票s)

2011年1月5日

CPOL

3分钟阅读

viewsIcon

87909

downloadIcon

496

框架使应用程序以更有条理、更高效的方式进行编码。它有助于新分配的开发人员在短时间内理解代码结构。对于大型应用程序来说,它是必不可少的。

引言

经历过大型应用程序开发的开发人员知道框架的必要性。在这方面,像团队负责人、技术负责人和项目经理(直至首席技术官)这样的更有经验的开发人员非常尊重它。他们从经验中知道,大型应用程序应该以非常有条理的方式开发,以便新分配的开发人员只需很短的时间就能掌握应用程序背后的开发结构,并为团队负责人或其他高级开发人员节省更多成本。他们也知道,在应用程序的开发完成后,维护将变得简单且经济高效。

背景

除此之外,我将着手开发一个 SQL 框架。我将通过演示来展示其必要性。

开始吧

  • 打开 SQL Management Studio

我想首先在 SQL Management Studio 中设计一个表结构,如下所示

SQLFramework/CustomerTableStructure.JPG

图 1

假设您在一个大型软件公司为一个大型项目工作,并且这个项目将花费很长时间。您在这个项目中有许多程序员在您手下工作。有时,程序员会离开您的软件公司,并被新程序员取代。到目前为止,这是一个大型项目,因此底层数据库的大小也会相应增大。假设您分配了一个任务给一个程序员,要求他创建一个带有适当验证和其他必要命令的存储过程来进行数据插入。

下面的过程是由程序员根据他分配的任务创建的。

CREATE PROCEDURE [dbo].[Customer_Set]
	@Name as varchar(50),
    	@Address as varchar(250),    
	@Mobile as varchar(50)
AS
BEGIN

	SET NOCOUNT ON

	--Validation
	IF @Name IS NULL
	BEGIN
		RAISERROR ('Name cannot be empty.',16,1)
	END

	IF LEN(@Name)<3
	BEGIN
		RAISERROR ('Name cannot be less than 3 characters.',16,1)
	END	

	--Data Insertion
	BEGIN TRY
		INSERT INTO [dbo].[Customer]
			([Name]
			,[Address]
			,[Mobile])
		VALUES
			(@Name
			,@Address			
			,@Mobile)
	END TRY
	BEGIN CATCH
		RETURN (0)
	END CATCH

 RETURN (1)
END

您还分配了另一位开发人员来编写供应商表的存储过程。

SQLFramework/SupplierTableStructure.JPG

图 2

然后像下面这样编写存储过程

CREATE PROCEDURE [dbo].[Supplier_Set]
@Name as varchar(50),
@Address as varchar(250),    
@Mobile as varchar(50)
AS
BEGIN

	SET NOCOUNT ON

	--Validation
	IF @Name IS NULL
	BEGIN
		RAISERROR ('Please enter supplier name.',16,1)
	END

	IF LEN(@Name)<3
	BEGIN
		RAISERROR ('Supplier name cannot be less than 3 characters.',16,1)
	END	

	--Data Insertion
	BEGIN TRY
		INSERT INTO [dbo].[Supplier]
			([Name]
			,[Address]
			,[Mobile])
		VALUES
			(@Name
			,@Address			
			,@Mobile)
	END TRY
	BEGIN CATCH
		RETURN (-1)
	END CATCH

 RETURN (1)
END

在审查上面两位程序员编写的两个存储过程的代码时,您会发现以下差异

IF @Name IS NULL
BEGIN
RAISERROR ('Name cannot be empty.',16,1)
END

IF LEN(@Name)<3
BEGIN
RAISERROR ('Name cannot be less than 3 characters.',16,1)
END	

BEGIN CATCH
		RETURN (0)
	END CATCH
 RETURN (1)

另一位程序员

IF @Name IS NULL
BEGIN
RAISERROR ('Please enter supplier name.',16,1)
END

IF LEN(@Name)<3
BEGIN
RAISERROR ('Supplier name cannot be less than 3 characters.',16,1)
END	

BEGIN CATCH
		RETURN (-1)
	END CATCH

 RETURN (1)

所以一位程序员写道

  1. 名称不能为空
  2. 名称不能少于 3 个字符
  3. RETURN (0)

另一位程序员写道

  1. 请输入供应商名称
  2. 供应商名称不能少于 3 个字符
  3. RETURN (-1)

对于相同类型的工作,他们没有使用相似的消息,并且他们还返回了 0 和 -1,这些是不易理解的。其他开发人员可能会写其他内容。所以这个系统不是一个通用的系统,也不是遵循相同的结构。

如果有很多由许多开发人员编写的上述存储过程,管理起来将非常困难。

系统应该遵循我称之为框架的结构进行开发,并且所有消息都应该有一个通用的、可读的返回类型,以及关于结构的、通用的其他内容。这将帮助我们轻松地管理系统,并付出更少的努力。

在这种情况下,我们可以通过编写一些额外的存储过程来构建一个框架,并且可以根据您的需求进行扩展,以构建您自己的框架。

让我们创建一个存储过程来设置一些常量变量,最有可能像 .NET 中的 Enum 。这些常量实际上将在其他常规过程中用于不同的操作类型。这些常量用于通用的系统开发。

CREATE PROCEDURE [dbo].[GetValidationConstraint]
	--Output values
	@EmptyCheck int OUTPUT,
	@LenCheck int  =NULL OUTPUT,
	@NoDataExist int =NULL OUTPUT,
	@True bit =NULL OUTPUT,	
	@False bit =NULL OUTPUT
AS
BEGIN
	SELECT @EmptyCheck=1
	SELECT @LenCheck =2
	SELECT @NoDataExist =3

	SELECT @True=1	
	SELECT @False=0
END

另一个过程是为整个应用程序提供通用的返回消息。

CREATE PROCEDURE [dbo].[ReturnMessage]
	--Success, Fail is the order of output parameter
	@Success int OUTPUT,	
	@Fail int OUTPUT	
AS
SET NOCOUNT ON

BEGIN
	SELECT @Fail=0
	SELECT @Success=1		
END

下面的过程是为应用程序提供通用消息的

CREATE PROCEDURE [dbo].[MessageHelper]
	--Input values
	@Field varchar(200) =NULL,
	@MinLenght int =NULL,
	@ValidationConstraint int,
	--Output values
	@ValidationMessage varchar(200) OUTPUT	
AS
BEGIN
	--Variables
	DECLARE @EMPTY_MESSAGE varchar(50),
		@MINIMUM_LENGHT_MESSAGE varchar(50),
		@NO_DATA_EXIST_MESSAGE varchar(50)

	DECLARE @EMPTY int,
		@LEN int,
		@NO_DATA_EXIST int	

	DECLARE @SUCCESSED int,
		@FAILED int	

	--Message Constraint
	SET @EMPTY_MESSAGE = 'cannot be empty.'
	SET @MINIMUM_LENGHT_MESSAGE ='cannot be less than'
	SET @NO_DATA_EXIST_MESSAGE = 'No record found.'
	
	--Get global values
	EXEC ReturnMessage @SUCCESSED output, @FAILED output
	EXEC GetValidationConstraint @EMPTY OUTPUT, @LEN OUTPUT, @NO_DATA_EXIST OUTPUT

	--Set message
	IF @ValidationConstraint = @EMPTY 
	BEGIN
		IF LEN(@Field)<=0
		BEGIN
			RAISERROR('Field name cannot be empty. _
				StoreProcedure/MessageHelper',16,1)	  	
			RETURN @FAILED
		END
		SELECT @ValidationMessage = @Field + ' ' + @EMPTY_MESSAGE	
	END

	IF @ValidationConstraint = @LEN
	BEGIN
		IF @MinLenght IS NULL OR @MinLenght <=0
		BEGIN
			RAISERROR('Minimum length cannot be empty. _
				StoreProcedure/MessageHelper',16,1)	  	
			RETURN @FAILED
		END
		ELSE
		BEGIN
			SELECT @ValidationMessage = @Field + ' ' + _
			@MINIMUM_LENGHT_MESSAGE + ' ' + CONVERT(varchar, @MinLenght)
		END
	END

	IF @ValidationConstraint = @NO_DATA_EXIST 
	BEGIN	  	
		SELECT @ValidationMessage = @NO_DATA_EXIST_MESSAGE			
	END
END

编写您的存储过程以将数据 insert Customer 表中

CREATE PROCEDURE [dbo].[Customer_Set]
	--Input values
	@Name as varchar(50),
    @Address as varchar(250),    
	@Mobile as varchar(50),
	--Output values
	@LASTID bigint OUTPUT,
	@MESSAGE varchar(200) =NULL OUTPUT
AS
SET NOCOUNT ON
BEGIN
	--Constraint Variables For Readable Return Value  
	DECLARE @SUCCESSED int,
		@FAILED int			

	--Constraint Variables For Readable Validation Operation  
	DECLARE @EMPTY int,
		@LEN int		
	
	BEGIN TRY
		--Get constraint value for success and failed
		EXEC ReturnMessage @SUCCESSED output, @FAILED output		
		--Get constraint value for validation. @EMPTY is for empty check 
                   --and @LEN is for length check common messaging system.
		EXEC GetValidationConstraint @EMPTY output, @LEN output
	
		--Validation
		IF LEN(@Name)=0
		BEGIN			
			EXEC MessageHelper 'Name', @EMPTY,@MESSAGE OUTPUT 
                                    --It will generate a common empty message.
			RETURN @FAILED-- Readable Failed Return
		END

		IF LEN(@Name)<3
		BEGIN			
			EXEC MessageHelper 'Name',3, @LEN,@MESSAGE OUTPUT 
                                  --It will generate a common length check message.
			RETURN @FAILED-- Readable Failed Return
		END
		
		--Data insertion
		INSERT INTO [dbo].[Customer]
           ([Name]
           ,[Address]
           ,[Mobile])
		VALUES
           (@Name
           ,@Address
           ,@Mobile)
			
			SELECT @LASTID=SCOPE_IDENTITY()
	END TRY
	BEGIN CATCH -- Error Trapping Section
		DECLARE @ErrorMessage nvarchar(4000);
		DECLARE @ErrorSeverity int;
		DECLARE @ErrorState int;
		
		SELECT 
			@ErrorMessage = ERROR_MESSAGE(),
			@ErrorSeverity = ERROR_SEVERITY(),
			@ErrorState = ERROR_STATE();
		
		RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState);
		RETURN @FAILED  -- Readable Failed Return
	END CATCH

	RETURN @SUCCESSED -- Readable Success Return
END

通过上述方式,系统中的所有消息都将保持通用。现在编写用于从 Customer 表中获取所有记录的存储过程。

CREATE PROCEDURE [dbo].[Customer_Get]	
	--Output values	
	@TOTAL_ROWS bigint OUTPUT,	
	@MESSAGE varchar(200) =NULL OUTPUT
	
AS
BEGIN
	SET NOCOUNT ON
	--Variables
	DECLARE @SUCCESSED int,
		@FAILED int		

	DECLARE @EMPTY int,
		@LEN int,
		@NO_DATA_EXIST int	
	
	BEGIN TRY
		--Get constraint value
		EXEC ReturnMessage @SUCCESSED OUTPUT, @FAILED OUTPUT		
		EXEC GetValidationConstraint @EMPTY OUTPUT, _
			@LEN OUTPUT,@NO_DATA_EXIST OUTPUT
	
		--Validation
		IF (SELECT COUNT(CustomerId) FROM  Customer )<= 0 
		BEGIN			
			EXEC MessageHelper '', @NO_DATA_EXIST,@MESSAGE OUTPUT 
				--It will generate common no data exist message.
			SELECT @TOTAL_ROWS=0
			 
			RETURN @SUCCESSED
		END
		
		--Data retrieval	
		SELECT [CustomerId]
		  ,[Name]
		  ,[Address]
		  ,[Mobile]	  
		FROM [dbo].[Customer]		

		--Get total rows	
		SELECT @TOTAL_ROWS=@@ROWCOUNT
		 
	END TRY
	BEGIN CATCH
		DECLARE @ErrorMessage nvarchar(4000);
		DECLARE @ErrorSeverity int;
		DECLARE @ErrorState int;
		
		SELECT 
			@ErrorMessage = ERROR_MESSAGE(),
			@ErrorSeverity = ERROR_SEVERITY(),
			@ErrorState = ERROR_STATE();		
		
		RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState);
		RETURN @FAILED
	END CATCH

	RETURN @SUCCESSED
END

编写用于从 Customer 表中 delete 记录的存储过程

CREATE  PROCEDURE [dbo].[Customer_DeleteById]
	--Input values
	@CustomerId bigint,	
	@MESSAGE varchar(200) =NULL OUTPUT
AS
BEGIN
	--Variables
	DECLARE @SUCCESSED int,
		@FAILED int			

	DECLARE @EMPTY int,
		@LEN int

	BEGIN TRY
		--Get constraint value
		EXEC ReturnMessage @SUCCESSED OUTPUT, @FAILED OUTPUT		
		EXEC GetValidationConstraint @EMPTY OUTPUT, @LEN OUTPUT
	
		--Validation
		IF @@CustomerId <=0
		BEGIN			
			EXEC MessageHelper 'Customer Id', @EMPTY,@MESSAGE OUTPUT
			RETURN @FAILED
		END
		
		--Data deletion	
		DELETE FROM [dbo].[Customer]
		  WHERE (CustomerId = @CustomerId)

	END TRY
	BEGIN CATCH
		DECLARE @ErrorMessage nvarchar(4000);
		DECLARE @ErrorSeverity int;
		DECLARE @ErrorState int;
		
		SELECT 
			@ErrorMessage = ERROR_MESSAGE(),
			@ErrorSeverity = ERROR_SEVERITY(),
			@ErrorState = ERROR_STATE();
		
		RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState);
		RETURN @FAILED
	END CATCH

	RETURN @SUCCESSED
END

因此,通过一些额外的存储过程,我们可以为 Web 或软件应用程序构建一个通用的消息传递和验证系统。通过构建一个通用系统或框架,我们可以减少软件项目的维护时间。而且整个系统也很容易理解。

结论

这个演示将帮助您开发您的 SQL 框架。

谢谢!

© . All rights reserved.