用多層架構構建一個簡易留言本 (轉)

gugu99發表於2007-08-16
用多層架構構建一個簡易留言本 (轉)[@more@]

用多層架構構建一個簡易留言本:namespace prefix = o ns = "urn:schemas--com::office" />

kaneboy@163

  .NET終於可以讓開發人員從ASP的麵條程式碼中脫身出來,以全新的方式來構建Web站點,就像 Application一樣,我們同樣可以用面向的、多層的方式來組織和構建Web Application。

  下面給出的是一個功能非常簡單的留言本,旨在揭示強大的能力和全新的開發方式。如果只相對留言本程式本身而言,大家可能懷疑用這麼多的氣力實現如此簡單的程式是否值得,但我說過,例子只是用來說明問題和描述解決方案。其實我認為,從維護和擴充的角度來說,即使再簡單的程式,從一開始就進行良好的設計也是非常值得的。

  留言本採用多層的方式來構建,下面的介紹為了方便大家理解,並未按照層次的順序介紹:

  一、資料實體(CMessageData類)

  CMessageData派生自DataSet,用來維護留言資料,在構造中,CreateDataTables()來增加一個用來儲存留言資料的DataTable,並加到自身的DataTable集合中。靜態屬性TableMap用來描述這個DataTable的DataColumn和中物理欄位的對映關係,資料訪問層將使用這個屬性來填充資料進CMessageData物件中。

  public class CMessageData : DataSet {

  public CMessageData() {

  this.CreateDataTables();

  }

  public static DataTableMapping TableMapping {

  get {

  DataTableMapping result = new DataTableMapping("t_gbook_postinfo", "MessageTable");

  result.ColumnMappings.Add("id", "Id");

  result.ColumnMappings.Add("last_reply_time", "LastReplyTime");

  //…..

  return result;

  }

  }

  private void CreateDataTables() {

  DataTable dt = new DataTable("MessageTable");

  dt.Columns.Add("Id", typeof(Int32));

  dt.Columns.Add("LastReplyTime", typeof(DateTime));

    // …..

  dt.Columns["Id"].AutoIncrement = true;

  dt.Columns["Id"].AutoIncrementSeed = 0;

  dt.Columns["Id"].AutoIncrementStep = -1;

    dt.PrimaryKey = new DataColumn[] {dt.Columns["Id"]};

  this.Tables.Add(dt);

  }

  AddedNewRow屬性返回一個新增進資料表的、空的DataRow,用於給邏輯層填充。FillDataFormDataBase()的兩個過載呼叫資料訪問層的相應方法來填充一個新的CMessageData物件並返回。UpdateToDatabase用於講自身的資料更改回資料庫。

public DataRow AddedNewRow()…

public static CMessageData FillDataFromDatabase(Int32 startRecord, Int32 maxRecord)…

public static CMessageData FillDataFromDatabase(Int32 id)…

public void UpdateToDatabase()…

 

二、資料訪問層(CDataAccess類)

負責連線資料庫,進行SIUD(,Insert,Update,Delete)操作。資料連線資訊放在AppParameters.xml中。

FillMessageData()的兩個過載建立新的CMessageData物件,填充資料,然後返回:

public static CMessageData FillMessageData(Int32 startRecord, Int32 maxRecord)

public static CMessageData FillMessageData(Int32 id)

UpdateMessageData()把引數中的CMessageData物件所作出的更改更新回資料庫:

public static Int32 UpdateMessageData(CMessageData messageData) {

  OleConnection conn = new OleDbConnection(CAppParameters.OleDbConnectionString);

  OleDbCommand cmdSelect = new OleDbCommand("Select username,last_reply_time,guest_name,guest_e,guest_website_name,guest_website_url,guest_oicq,guest_ip,guest_post_time,guest_text,reply_data From t_gbook_postinfo", conn);

  OleDbCommand cmdInsert = new OleDbCommand();

  cmdInsert.Connection = conn;

  cmdInsert.CommandText = "Insert Into t_gbook_postinfo (last_reply_time,guest_name,guest_,guest_website_name,guest_website_url,guest_oicq,guest_ip,guest_post_time,guest_text,reply_data) Values (@last_reply_time,@guest_name,@guest_email,@guest_website_name,@guest_website_url,@guest_oicq,@guest_ip,@guest_post_time,@guest_text,@reply_data)";

  cmdInsert.Parameters.Add("@last_reply_time", OleDbType.DBDate, 0, "last_reply_time");

  cmdInsert.Parameters.Add("@guest_name", OleDbType.VarWChar, 255, "guest_name");

  //…

  OleDbCommand cmdUpdate = new OleDbCommand();

  cmdUpdate.Connection = conn;

  cmdUpdate.CommandText = "Update t_gbook_postinfo Set last_reply_time=@last_reply_time,guest_name=@guest_name,guest_email=@guest_email,guest_website_name=@guest_website_name,guest_website_url=@guest_website_url,guest_oicq=@guest_oicq,guest_ip=@guest_ip,guest_post_time=@guest_post_time,guest_text=@guest_text,reply_data=@reply_data Where (id=@Original_id)";

  cmdUpdate.Parameters.Add("@last_reply_time", OleDbType.DBDate, 0, "last_reply_time");

  cmdUpdate.Parameters.Add("@guest_name", OleDbType.VarWChar, 255, "guest_name");

  //…

  OleDbCommand cmdDelete = new OleDbCommand();

  cmdDelete.Connection = conn;

  cmdDelete.CommandText = @"Delete From t_gbook_postinfo where (id = @Original_id)";

  cmdDelete.Parameters.Add("@Original_id", OleDbType.Integer, 0, "id").Version = DataRowVersion.Original;

  OleDbDataAdapter ada = new OleDbDataAdapter(cmdSelect);

  ada.InsertCommand = cmdInsert;

  ada.UpdateCommand = cmdUpdate;

  ada.DeleteCommand = cmdDelete;

  ada.TableMappings.Add(CMessageData.TableMapping);

 

  return ada.Update(messageData, "t_gbook_postinfo");

  }

把資料訪問層單獨提取出來的好處就是其他層都不會直接和資料庫打交道,如果我們把資料庫從Access改成Server只需要用一個新的CDataAccess類替換現在的即可。在原始碼中,就有一個使用了Odbc.Net實現的COdbcDataAccess,用這個替換掉CDataAccess不會對程式中其他部分產生任何影響,我們可以利用Odbc.Net的訪問能力,把資料庫改為、Forpro等。

三、邏輯層

這個留言本的邏輯層很簡單,由三個類組成,CMessage用來描述一條留言,CReply用來描述一條回覆,CReplyCollection集合類用來描述多條回覆。

CMessage提供了一個過載的建構函式:

public CMessage(DataRow row)

我們可以用CMessageData中個一個DataRow的資料來初始化一個CMessage物件。

public void FillDataRow(DataRow row)

這個函式則把自身的資料填充進引數中的DataRow物件。我們用類似:

GetMessage().FillDataRow(messageData.AddedNewRow())

這樣的程式碼就可以把一條新的留言內容新增到一個CMessageData物件中,其中GetMessage()是頁面上收集填入的資料並返回一個CMessage的一個方法。

public CReplyCollection Replys

這個屬性用來公開對自身這條留言的所有回覆。

四、介面層 - 使用者

為了方便我們把一個CMessage物件和頁面上顯示出來的一條留言繫結在一起,把一個CReply物件與頁面上顯示出來的一條回覆繫結在一起,我們製作兩個UserControl。MessageBlock控制元件用來顯示一條留言,它透過屬性:

public CMessage Message

來物件公開CMessage介面,我們只需要把一個CMessage物件賦值給這個屬性,就可以讓這個控制元件顯示CMessage物件所表示的留言的內容。

ReplyBlock控制元件用來顯示一條回覆,同樣透過屬性:

public CReply Reply

來公開一個CReply型別的介面。

在MessageBlock控制元件中,我們根據對應的CMessage物件的Replys屬性中所包含的回覆,透過LoadControl()方法來動態載入ReplyBlock控制元件,並放置在一個PlaceHolder型別的Web控制元件中。

五、介面層 - 頁面

現在頁面的顯示非常簡單了,我們在主頁面(default..cs)中建立一個CMessageData物件,填充資料,再用LoadControl()方法來載入MessageBlock控制元件來顯示留言就可以了。

CMessageData messageData = CMessageData.FillDataFromDatabase((iPage - 1) * iPageSize, iPageSize);

for(Int32 i = 0; i < messageData.Count; ++i) {

  MessageBlock msg = (MessageBlock)LoadControl("MessageBlock.ascx");

  msg.Message = new CMessage(messageData.Tables["MessageTable"].Rows[i]);

  hldMessage.Controls.Add(msg);

}

以一個功能齊全的留言本來衡量,我們上面構建的留言本缺少刪貼、管理功能,但是隻要基礎架構出來,完善和擴充套件功能是非常簡單的。

上面的留言本展示了一個基礎的程式架構,真正大型程式的架構可能要複雜上很多。比如資料實體類我們可以把欄位資訊和對映資訊放入一個XML檔案中,然後我們只需要建立一個通用的資料實體類,透過載入不同的XML檔案就可以描述不同的資料實體;在資料複雜的情況下,維護各個資料間的關係也是一個挑戰。

可以在到,如果你要用,記住修改一下AppParameters.xml檔案,至少裡面連線字串的Access檔案的路徑是需要更改的(你可以乾脆在global.asax中用MapPath()來動態得到這個路徑:),CAppParameters.cs檔案中的_sAppParameterFileName字串的值也要根據實際情況作出改變(同樣你可以用MapPath():),然後在IIS中建立一個名為gbook的虛擬目錄來承載這個專案。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-960634/,如需轉載,請註明出處,否則將追究法律責任。

相關文章