對資料訪問層的重構(及重構中Perl的應用)

來源:互聯網
上載者:User

標籤:blog   http   io   os   使用   ar   for   檔案   資料   

  以前上學的時候,聽到“一個學生在畢業後剛剛開始編程的頭幾年中,寫出的代碼多半是垃圾”這樣的說法,均不屑一顧。現在工作一年多了,越發感覺自己代碼中疏漏處甚多,故近來常做亡羊補牢的重構之舉。拿自己4個月前寫的資料訪問層來說,這個層位於整個系統的最底端,根據傳入的sql語句進行查詢和更新操作。就拿查詢來說吧,我當時覺得很簡單,寫出來的方法是這樣的:

 1//程式碼片段1
 2public DataTable ExecuteQuery(string cmdText)
 3{
 4    if (cmdText == null)
 5        return null;
 6
 7    SqlDataAdapter adapter = new SqlDataAdapter(cmdText, connection);
 8    DataTable table = new DataTable();
 9    try
10    {
11        adapter.Fill(table);
12    }
13    catch (SqlException e)
14    {
15
16        HttpContext.Current.Response.Redirect(string.format("~/ErrorPage?ErrorString={0}", HttpContext.Current.Server.UrlEncode(e.Message)));
17    }
18    finally
19    {
20            connection.Close();
21    }
22
23    return table;
24}


而此方法都是這樣被我調用的:

1//程式碼片段2
2string cmd = "select * from MaterialClass where MaterialClassCode = {0}";
3cmd = string.Format(cmd, scope);
4DataTable table = new BitAECSqlExe().ExecuteQuery(cmd);


有心的朋友很容易就能看出,如此的代碼是非常脆弱的,根本無法應付查詢字串中出現特殊字元的情況(單引號,百分比符號等)。程式容錯性差不說,還容易遭到sql注入的攻擊。另外,對於sql操作可能拋出的異常,這裡捕獲之後就跳轉到出錯頁的方式也是很糟糕的;因為這段底層代碼,除了會被頁面調用以外,還會被其他一些不是由用戶端請求引發的功能所調用(如部署到伺服器上的windows服務,處理複雜任務的專用背景工作執行緒等),在這些調用環境裡HttpContext.Current是沒有意義的。實際上,在這種底層的代碼裡,只能對異常作必要的處理,至於究竟是跳轉到一個友好的錯誤提示介面,還是寫入錯誤記錄檔,應當交給更高層的代碼去決定。
  對這部分的重構其實很簡單,那就是在進行查詢的時候,對於所有參數都以SqlParameter進行封裝。重構中新增了方法PrepareCommand,用來得到我們需要的SqlCommand對象。對ExecuteQuery的重構如下:

 1//程式碼片段3
 2private SqlCommand PrepareCommand(string cmdText, SqlParameter[] cmdParms)
 3{
 4    if (cmdText == null)
 5        throw new ArgumentNullException();
 6
 7    SqlCommand cmd = new SqlCommand(cmdText, connection);
 8    if((cmdParms!=null)&&(cmdParms.Length>0))
 9        foreach (SqlParameter param in cmdParms)
10        {
11            cmd.Parameters.Add(param);
12        }
13
14    return cmd;
15}
16
17public DataTable ExecuteQuery(string cmdText, SqlParameter[] sqlParams)
18{
19    if (cmdText == null)
20        return null;
21
22    SqlDataAdapter adapter = new SqlDataAdapter(this.PrepareCommand(cmdText,sqlParams));
23    DataTable table = new DataTable();
24    try
25    {
26        adapter.Fill(table);
27    }
28    catch (SqlException e)
29    {
30        throw e;
31    }
32    finally
33    {
34        if (connection.State != ConnectionState.Open)
35            connection.Close();
36    }
37
38    return table;
39}

  上面重構的是ExecuteQuery方法的定義部分,這其實只是重構的開始,因為現有代碼中充滿了類似程式碼片段2那樣的方法調用,都需要改成如下的形式:

1//程式碼片段4
2string cmd = "select * from MaterialClass where MaterialClassCode = @MaterialClassCode and CompanyName = @CompanyName";
3SqlParameter[] SqlParams = 
4{ 
5    new SqlParameter("@MaterialClassCode",MaterialClassCode ),
6    new SqlParameter("@CompanyName",CompanyName )
7}
8DataTable table = new BitAECSqlExe().ExecuteQuery(cmd);

   比照一下上面貼出的程式碼片段2和程式碼片段4,它們之間的差異就是我很希望自己能通過Regex跨越的鴻溝(一個一個手工去改的話實在太累了,一百多處啊,呵呵)。需要注意的是,查詢語句中可能出現的參數個數是不定的,每個檔案中可能包含的方法調用的數量也是不定的。本想寫一個C#的console小程式來完成這個大量操作,但又總覺得殺雞用牛刀,後來寫了一個簡單的perl指令碼,利用perl強大的文本處理能力,很容易就實現了這個功能。指令碼代碼如下:

 1use FileHandle;
 2use File::Find;
 3use strict;
 4
 5#全域變數
 6my $directory = "E:/GEA52_SVN/GEA52/Web";
 7#my $directory = "E:/Temp/Perl";
 8
 9find(\&editFile, $directory);
10
11#使用這個方法來修改每一個代碼檔案
12#xingyk 20070702
13sub editFile() 
14{
15    if ( -f and /.cs?/ ) 
16    {
17        my $file = $_;
18        open FILE, $file;
19        my @lines = <FILE>;
20        close FILE;
21        
22        my @maArr;
23        for my $line ( @lines ) 
24        {
25            @maArr = $line =~ /\s+(\w+)\s*={\d}/g;
26            
27            #先替換原有查詢字串
28            $line =~ s/\s+(\w+)\s*={\d}/ $1=\@$1 /g;
29            #接下來添加SqlParameter數組的預設構造器
30            my $sqlParam = "\n\tSqlParameter[] sqlParams = { ";
31            if(@maArr>0)
32            {
33                for(@maArr)
34                {
35                    $sqlParam = $sqlParam."\t\tnew SqlParameter(\"@".$_."\", ".$_."),\n";
36                }
37                $line = $line.$sqlParam."\t\t\t};\n";
38            }
39            
40        }
41
42        open FILE, ">$file";
43        print FILE @lines;
44        close FILE;
45    }
46}

 

對資料訪問層的重構(及重構中Perl的應用)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.