不用第三方之C#自己實現Visual SourceSafe 管理Oracle的程式

來源:互聯網
上載者:User
還是自己寫的東西順手些,至少啟動時沒有怪叫。。。

下面向大家介紹如何使用VSS管理Oracle中寫的代碼。

一、簡介

    Visual SourceSafe(以下簡稱VSS) 是微軟公司推出的一款版本管理軟體,可以很方便的管理原始碼的版本和處理多方協作,目前相似的軟體有很多,而且有很多也是相當不錯的,但是在本文所描述的功能中,VSS足以完成我們要求的任務。

    Oracle是一款大型的資料庫軟體,號稱管理著世界上60%的資料庫,在這裡不對其強大的功能進行更多的描述。在Oracle中,可以使用PL/SQL語言編寫函數(Function),預存程序(Procedure),及包(Package),一般情況下,這些程式都是以原始碼的形式儲存於資料庫中(特別的加密情況除外)。

    在程式經常需要修改的時候,版本管理顯的特別重要,本人在使用過程中就經常為此事煩惱。以往的作法是在每次修改程式之前或之後,都把預存程序之類的存成一個檔案,在檔案名稱後加一個日期,表示程式的版本,然後放入專用的目錄中,以便曆史追溯,這樣就會造成一個程式會存在大量的檔案,給後期的維護工作帶來很大的麻煩。後來又嘗試把產生的檔案放入VSS中管理,但是使用很煩瑣,需要先存成檔案,然後在VSS用戶端中checkin,如果需要把很多的程式checkin到VSS中,可是個不小的工作量,在使用Oracle11i系統的時候,apps使用者下的package達到3萬多個,原始碼加起來有1G的數量級,如果用上面的工作方式來checkin,恐怕日子不好過了。

    因此,為瞭解決以上問題,本人用C#開發了一個專用的程式,暫且命名為“Visual SourceSafe for Oracle”,也即是說,它是專門為Oracle服務的VSS用戶端,如果需要使用此程式,有個前提條件,就是所在的機器必須裝有Oracle的用戶端軟體和VSS的用戶端軟體,因為程式中要用到它們相應的組件。

    首先需要看的是如果利用自己的程式向VSS中checkin內容,這是本程式最關鍵的地方,在經過資料尋找後,發現可以利用VSS中的SSAPI.DLL檔案來實現這個功能,這個DLL是VSS提供的專門用於處理VSS事物的對外的API介面,在vs中可以直接引用,vs會自動產生一個託管的類,名字為Interop.SourceSafeTypeLib.dll,在這個API中,有我們所需要的一切的API函數,包括checkin checkout additem等,在後面會有介紹。

    說完VSS這邊,要再來說一下Oracle這邊,我們必須把程式從資料庫裡取出來才能寫到VSS中,否則VSS也是無用武之地了。Oracle的Function/Procedure/Package(Package Header/Package Body)全部儲存於視圖USER_SOURCE中,在這個視圖中,幾個欄位的含義如下:

    NAME:程式的名字,可以是包的名字,也可以是預存程序的程式

    TYPE:程式的類型,如包或預存程序等

    LINE:行號,每條記錄只儲存程式的一行的值

    TEXT:程式中每行的內容

    根據以上結構,要找出一個預存程序的具體內容應該是找到NAME=預存程序名的所有TEXT的欄位的值,並且按LINE欄位來排序,如下所示:

select text from USER_SOURCE where name='XXXX' order by line

    至於如何把這些行變成一個字串,所有程式設計語言都應該是差不多的,只要依次把所有行的內容簡單的加起來就行了,當然,不要忘記在每行的中間加一個分行符號,這樣程式才像以前的樣子,否則就都成一行了,難看又難懂。

二、實現

    1.登入

    在程式實現方面,第一部分就是要製作一個登入介面,這個登入與VSS登入不同,與Oracle登入也不同,因為在同一個登入介面裡,我同時處理了登入Oracle和VSS兩者,介面如:

    根據介面上的字面意思,可以很容易知道這個介面如何使用。

    在登入程式裡,使用了一個小技巧,就是利用了註冊表,在每次登入成功後,會把當前的資料庫登入使用者名稱,資料庫連接串,VSS登入使用者名稱,VSS設定檔名寫入到註冊表中,下次登入的時候,直接從註冊表中取出,可以提高程式的使用效率。

    讀取註冊表的代碼部分如下:

Microsoft.Win32.RegistryKey key =

Microsoft.Win32.Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, false);

if (key != null)

{

txtOracleUserName.Text = key.GetValue("ORACLE_USER_NAME").ToString();

txtOracleDB.Text = key.GetValue("ORACLE_CONNECTION_STRING").ToString();

txtSSUserName.Text = key.GetValue("SS_USER_NAME").ToString();

txtSSDB.Text = key.GetValue("SS_CONNECTION_STRING").ToString();

}

    其中REGISTRY_KEY= "SOFTWARE\\VSS4Oracle\\Login",表示在註冊表中儲存的路徑。

    登入成功後寫註冊表的代碼如下:

Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, true);

if (key == null)

{

key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(REGISTRY_KEY);

}

key.SetValue("ORACLE_USER_NAME",txtOracleUserName.Text);

key.SetValue("ORACLE_CONNECTION_STRING",txtOracleDB.Text);

key.SetValue("SS_USER_NAME",txtSSUserName.Text);

key.SetValue("SS_CONNECTION_STRING",txtSSDB.Text);

    本模組只處理簡單的登入,登入後把表單上的各個參數傳給主表單,資料庫使用者的校正和VSS使用者的校正由主表單來完成。為了把參數傳給主表單,需要給本表單增加幾個屬性,用來表示表單上各個檔案框控制項的值,之所以不直接使用控制項的值而增加屬性來表示,是因為控制項預設狀態是私人變數,不提倡把私人變數變成公有變數。屬性如下:

public string OracleUserName

{

get{return txtOracleUserName.Text;}

}

public string OraclePassword

{

get{ return txtOraclePassword.Text;}

}

public string OracleDB

{

get{

if (txtOracleDB.Text == "")

{

return "(local)";

}

else

{

return txtOracleDB.Text;

}

}

}

public string SSUserName

{

get{ return txtSSUserName.Text;}

}

public string SSPassword

{

get{ return txtSSPassword.Text;}

}

public string SSDB

{

get{return txtSSDB.Text;}

}

2.列出VSS中的項目及內容列表

    由登入表單得到各種需要的參數後,就轉到主表單,主表單在初始狀態下,最主要的任何是把VSS中相關的項目列出來供使用。

    您的VSS中可能會儲存Oracle以外的程式,但是在本程式中,只對我們相關的Oracle程式部分進行顯示,其它內容不做處理,VSS中顯示的項目結構如下:

$/Oracle/串連串名字/Oracle使用者名稱/

Function

Package

Procedure

Sequence

Synonym

Table

Trigger

View

    以上幾類在Oracle中都是以可以找到它們的原始碼,如果您需要增加您新的類型,可以直接在後面的程式中進行修改。

主程式的介面如下:

系統在每次登入的時候,都會檢查VSS中是否包括所需要的上述的項目結構,如果不存在,則自動建立。過程如下:

在主表單的代碼中要添加一個新的命名空間的引用:using SourceSafeTypeLib;

然後在其它操作之前要把它VSS的資料庫,代碼如下:

db = new VSSDatabaseClass();

db.Open(ssDB,ssUserName,ssPassword);

其中db是一個私人變數,類型就是VSSDatabaseClass

開啟資料庫後,開始建立所需要的項目,代碼如下:

string root = "$/Oracle/" + oracleDB + "/" + oracleUserName ;

CreateProjectTree(root);

string[] items = new string[8];

items[0] = "Table";

items[1] = "View";

items[2] = "Trigger";

items[3] = "Function";

items[4] = "Procedure";

items[5] = "Package";

items[6] = "Sequence";

items[7] = "Synonym";

VSSItem item = db.get_VSSItem("$/",false);

for(int i = 0; i < items.GetLength(0); i++)

{

try

{item.NewSubproject(root + "/" + items[i],"created");}

catch(Exception ex)

{System.Diagnostics.Debug.WriteLine(ex.Message);}

}

    請注意建立的時候用的是try/catch結構,也就是當需要建立的項目是存在的時候,就跳過去直接處理其它的事物,因為我沒有發現db中有一個函數來檢測是否存在一個項目,所以只能用此種變通的方式來處理。

    經過上面的建立工作,在VSS中就已經存在了需要的結構了,您可以直接使用VSS的用戶端去查看,如果是第一次使用,那麼每個項目的裡面是沒有任何內容的,當然了,是因為您還沒有進行任何的checkin操作。

   在建立了VSS結構後,主表單中有一個TreeView控制項,用來顯示這個結構,代碼如下:

rtbMessages.AppendText("Building Source Safe project hierarchy ... \n");

Application.DoEvents();

Cursor = Cursors.WaitCursor;

tvProject.Nodes.Clear();

try

{

string root = "$/Oracle/" + oracleDB + "/" + oracleUserName;

tvProject.Nodes.Add(root);

VSSItem vssProj = db.get_VSSItem(root , false);

IVSSItems items = vssProj.get_Items(false);

foreach(VSSItem item in items)

{

tvProject.Nodes[0].Nodes.Add(item.Name);

}

tvProject.Nodes[0].Expand();

}

catch(Exception ex)

{

rtbMessages.AppendText("\n\n" + ex.ToString());

}

finally

{

Cursor = Cursors.Default;

rtbMessages.AppendText("\n\n... Done");

}

    上述功能只是顯示一個樹的結構,並不包括具體的內容,比如具體有哪些函數,有哪些的預存程序,在上述代碼中還沒有體現。這部分的顯示功能放在左側的樹的after_selected事件中,即選擇任何一個項目,就顯示該項目的具體情況。

    根據可以看出,系統中有兩個package,根據表徵圖可以看出兩個package有所不同,第一種表徵圖表示該對象已經儲存於VSS中,而第二個表徵圖表示此對象在VSS中系統還從沒有被簽入過。

3.簽入(checkin)

    checkin是指把資料庫中的對象的代碼匯入到VSS系統中,簽入有幾種方式,在對象上點右鍵,或在左側的分類樹中點右鍵都會彈出簽入的對話方塊,作用是相同的,但是作用的範圍有所不同,如果在對象上點簽入,就是只針對所選擇的對象進行簽入(可以是單選也可以是多選),如果在左側的分類樹上點簽入,會整個目錄進行簽入,比如在Package上籤入,會把系統的所有的Package簽入,如果系統中Package較多,而實際更新的並不多,這種作法將很費時間;如果在$/Oracle/(local)/scott這樣的根結點上點右鍵,則會把所有的Function/Procedur/Package/…等所有的對象全部簽入,在一個大系統中,這將是一個非常費時間的過程,要根據實際情況選擇使用,而如果是一個比較小的系統,經常採用這種方式,會把一些丟掉沒有簽入的對象補到VSS中,是一個比較好的辦法。

    簽入的的對話方塊我根據我當前的需求,只設計了一個文字框,就是check的comment,如:

    用於記錄本次簽入的注釋。

    在簽入之前,我們需要得到Oracle對象的具體內容,如Package,我們要得到具體的代碼才可以,具體的取法在上面已經提到。

    因為VSS的特性決定,我們在得到代碼後,必鬚生成一個實際的物理檔案,才可以被VSS使用,因為使用StreamWriter對象把所得到的內容產生一個檔案,如下:

string fileName = tempDir + "\\" + contentName;

if (File.Exists(fileName))

{

File.SetAttributes(fileName,FileAttributes.Normal);

File.Delete(fileName);

}

StreamWriter writer = new StreamWriter(fileName,false,System.Text.Encoding.Default);

writer.Write(content);

writer.Close();

    在上面的代碼中,contentName表示對象名,也將用作檔案名稱,tempDir可以是一個臨時目錄,也可以是您自己強行指定的一個目錄,content是從DB中產生的對象的實際的代碼。

    在Oracle的命名規則中,”$” 這個字元是合法的,而在VSS中,這個字元表示VSS的根路徑,所以變為不合法的字元,也就是如果某個包的名字包括這個字元,將不能正常checkin,在Oralce11i系統中,這個字元被大量的用在package的名字中。為瞭解決這個問題,需要把$字元替換成別的字元,並且在組建檔案的時候,需要作業系統也能正常識別,經過測試,選擇了“@”這個字元,因此上述的代碼改成如下:

    string fileName = tempDir + "\\" + contentName.Replace("$","@");

    在最後的簽入的步驟中,直接使用VSSItem的checkin方法或Add方法就可以了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.