天天看點

綜合應用WPF/WCF/WF/LINQ之二十七:代碼生成器之DBMLToProcedure

本存儲過程代碼生成器能處理如下幾種形式的存儲過程:

  1、形如InsertTableName的存儲過程,用于插入某條記錄。

  2、形如UpdateTableNameByFieldName的存儲過程,用于根據某個字段更新某條記錄。

  3、形如DeleteTableNameByFieldName的存儲過程,用于根據某個字段删除某條記錄。

  4、形如GetTableNames的存儲過程,用于查詢所有記錄。

  5、形如GetTableNamesByFieldName的存儲過程,用于根據某個字段查詢記錄。

  6、形如GetTableNamesByPage的存儲過程,用于根據頁碼查詢記錄。

  7、形如GetTableNamesByFilter的存儲過程,用于根據過濾條件、頁碼查詢記錄。

  在存儲過程沒有過多業務邏輯的情況下,一般上述集中形式的存儲過程即能滿足一般系統的需要。如果您需要支援更多的形式,請自行修改代碼。

  各種形式的存儲過程舉例如下:

  1、形如InsertTableName的存儲過程。對該存儲過程,我們主要需要擷取該表的字段名、類型和長度等。在以前,我們需要通過讀取資料的Schema的方式來獲得字段的這些屬性,現在有了LINQ,我就可以直接從DBML檔案中擷取了。

    1 IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'InsertFunction')

    2     BEGIN

    3         DROP Procedure [InsertFunction]

    4     END

    5 

    6 GO

    7 

    8 CREATE Procedure [InsertFunction]

    9     (

   10         @FunctionId Int = NULL,

   11         @FunctionName NVarChar(50) = NULL,

   12         @FunctionDescription NVarChar(255) = NULL

   13     )

   14 

   15 AS

   16 

   17     BEGIN

   18         INSERT INTO [Function] ([FunctionId],

   19                                 [FunctionName],

   20                                 [FunctionDescription])

   21         VALUES (@FunctionId,

   22                 @FunctionName,

   23                 @FunctionDescription)

   24     END

   25 

   26 GO

  擷取了足夠的資訊後,這個存儲過程的拼湊就可以完成了。主體拼湊代碼如下,其中24和16用于生成空格,以便看到上面每個字段分一行的整齊代碼。

    1         strContentes += string.Format("        INSERT INTO [{0}] ({1})" + "\n", table, strColumns.GetColumns(24 + table.Length));

    2         strContentes += string.Format("        VALUES ({0})" + "\n", strColumns.GetVariables(16));

  2、形如GetTableNamesByFilter的存儲過程。在有很多可選過濾條件的情況下,我們不可能為每一種組合建立一個存儲過程,這時,我們可以采用拼湊Where後面的SQL語句的方式實作查詢。這時,我們除了跟上一個存儲過程一樣擷取字段資訊外,還需要處理翻頁、拼湊SQL語句等。我們可以采用嵌套Select語句的方式實作拼湊和翻頁。

    1 IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'GetFunctionsByFilter')

    3         DROP Procedure [GetFunctionsByFilter]

    8 CREATE Procedure [GetFunctionsByFilter]

   10         @FunctionName NVarChar(50) = NULL,

   11         @PageSize Int = NULL,

   12         @PageIndex Int = NULL,

   13         @RecordCount Int = NULL OUTPUT

   14     )

   15 

   16 AS

   17 

   18     BEGIN

   19         DECLARE @MinIndex Int

   20         DECLARE @MaxIndex Int

   21         SET @MinIndex = (@PageIndex - 1) * @PageSize + 1

   22         SET @MaxIndex = @MinIndex + @PageSize - 1

   23 

   24         DECLARE @Where NVarChar(MAX)

   25         SET @Where = '0 = 0'

   26         IF @FunctionName IS NOT NULL

   27             SET @Where = @Where + ' AND [Function].[FunctionName] LIKE ''%' + @FunctionName + '%'''

   28 

   29         DECLARE @Record NVarChar(MAX)

   30         SET @Record = 'SELECT ROW_NUMBER() OVER(ORDER BY [Function].[FunctionId]) AS [Index],

   31                               [Function].[FunctionId],

   32                               [Function].[FunctionName],

   33                               [Function].[FunctionDescription]

   34                        FROM [Function]

   35                        WHERE' + ' ' + @Where

   36 

   37         DECLARE @Sql NVarChar(MAX)

   38         SET @Sql = 'SELECT @RecordCount = COUNT(*)

   39                     FROM (' + @Record + ') DERIVEDTBL

   40 

   41                     SELECT [FunctionId],

   42                            [FunctionName],

   43                            [FunctionDescription]

   44                     FROM (' + @Record + ') DERIVEDTBL

   45                     WHERE [Index] >= @MinIndex AND [Index] <= @MaxIndex'

   46 

   47         DECLARE @Parameter NVarChar(MAX)

   48         SET @Parameter = '@MinIndex Int, @MaxIndex Int, @RecordCount Int OUTPUT'

   49 

   50         EXEC sp_executesql @Sql, @Parameter, @MinIndex, @MaxIndex, @RecordCount OUTPUT

   51     END

   52 

   53 GO

  擷取了足夠的資訊後,這個存儲過程的拼湊就可以完成了。主體拼湊代碼如下。值得注意的是,當可選參數為String類型時,您需要處理腳本注入的問題(筆者這裡并未處理)。

    1     strContentes = strContentes + "        DECLARE @MinIndex Int" + "\n";

    2     strContentes = strContentes + "        DECLARE @MaxIndex Int" + "\n";

    3     strContentes = strContentes + "        SET @MinIndex = (@PageIndex - 1) * @PageSize + 1" + "\n";

    4     strContentes = strContentes + "        SET @MaxIndex = @MinIndex + @PageSize - 1" + "\n";

    5     strContentes = strContentes + "        " + "\n";

    6     strContentes = strContentes + "        DECLARE @Where NVarChar(MAX)" + "\n";

    7     strContentes = strContentes + "        SET @Where = '0 = 0'" + "\n";

    8 

    9     for (int i = 0; i < method.GetParameters().Length - 3; i++)

   10     {

   11         strContentes += string.Format("        IF @{0} IS NOT NULL" + "\n", method.GetParameters()[i].GetName());

   12 

   13         if (method.GetParameters()[i].ParameterType.ToSqlDbType().ToString() == "NVarChar")

   14         {

   15             strContentes += string.Format("            SET @Where = @Where + ' AND [{0}].[{1}] LIKE ''%' + @{2} + '%'''" + "\n", table, method.GetParameters()[i].GetName(), method.GetParameters()[i].GetName());

   16         }

   17         else if (method.GetParameters()[i].ParameterType.ToSqlDbType().ToString() == "DateTime" && method.GetParameters()[i].GetName().StartsWith("Begin") == true)

   18         {

   19             strContentes += string.Format("            SET @Where = @Where + ' AND [{0}].[{1}] >= ''' + CONVERT(NVarChar, @{2}, 101) + ' ' + '00:00:00' + ''''" + "\n", table, method.GetParameters()[i].GetName().Substring(5), method.GetParameters()[i].GetName());

   20         }

   21         else if (method.GetParameters()[i].ParameterType.ToSqlDbType().ToString() == "DateTime" && method.GetParameters()[i].GetName().StartsWith("End") == true)

   22         {

   23             strContentes += string.Format("            SET @Where = @Where + ' AND [{0}].[{1}] <= ''' + CONVERT(NVarChar, @{2}, 101) + ' ' + '23:59:59' + ''''" + "\n", table, method.GetParameters()[i].GetName().Substring(3), method.GetParameters()[i].GetName());

   24         }

   25         else

   26         {

   27             strContentes += string.Format("            SET @Where = @Where + ' AND [{0}].[{1}] = ''' + CONVERT(NVarChar, @{2}) + ''''" + "\n", table, method.GetParameters()[i].GetName(), method.GetParameters()[i].GetName());

   28         }

   29     }

   30 

   31     strContentes = strContentes + "        " + "\n";

   32     strContentes = strContentes + "        DECLARE @Record NVarChar(MAX)" + "\n";

   33     strContentes += string.Format("        SET @Record = 'SELECT ROW_NUMBER() OVER(ORDER BY [{0}].[{1}]) AS [Index]," + "\n", table, strKey);

   34     strContentes += string.Format("                              {0}" + "\n", strColumns.GetColumns(table, infos, 30, true));

   35     strContentes += string.Format("                       FROM {0}" + "\n", infos.GetFroms(table, 23));

   36     strContentes = strContentes + "                       WHERE' + ' ' + @Where" + "\n";

   37     strContentes = strContentes + "        " + "\n";

   38     strContentes = strContentes + "        DECLARE @Sql NVarChar(MAX)" + "\n";

   39     strContentes = strContentes + "        SET @Sql = 'SELECT @RecordCount = COUNT(*)" + "\n";

   40     strContentes = strContentes + "                    FROM (' + @Record + ') DERIVEDTBL" + "\n";

   41     strContentes = strContentes + "                    " + "\n";

   42     strContentes += string.Format("                    SELECT {0}" + "\n", strColumns.GetColumns(table, infos, 27, false));

   43     strContentes = strContentes + "                    FROM (' + @Record + ') DERIVEDTBL" + "\n";

   44     strContentes = strContentes + "                    WHERE [Index] >= @MinIndex AND [Index] <= @MaxIndex'" + "\n";

   45     strContentes = strContentes + "        " + "\n";

   46     strContentes = strContentes + "        DECLARE @Parameter NVarChar(MAX)" + "\n";

   47     strContentes = strContentes + "        SET @Parameter = '@MinIndex Int, @MaxIndex Int, @RecordCount Int OUTPUT'" + "\n";

   48     strContentes = strContentes + "        " + "\n";

   49     strContentes = strContentes + "        EXEC sp_executesql @Sql, @Parameter, @MinIndex, @MaxIndex, @RecordCount OUTPUT" + "\n";

  其它類型的存儲過程我就不一一列舉。

  在開始使用這個代碼生成器之前,請先手工完成Eallies.OA.DAL.Interface這個項目,這個項目包含所有的DAL層需要實作的接口。這個代碼生成将根據這個接口生成相應名稱、參數等的存儲過程。

  本存儲過程代碼生成器的調用方法請參考Eallies.OA.Generator目錄下的GenerateProcedure.bat檔案。

本文轉自 Eallies 51CTO部落格,原文連結:http://blog.51cto.com/eallies/79013,如需轉載請自行聯系原作者