這篇文章討論如何在c#中實(shí)現(xiàn)3層架構(gòu),使用ms access數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)。在此,我在3層架構(gòu)中實(shí)現(xiàn)一個(gè)小型的可復(fù)用的組件保存客戶數(shù)據(jù)。并提供添加,更新,查找客戶數(shù)據(jù)的功能。
背景
首先,我介紹一些3層架構(gòu)的理論知識(shí)。簡單說明:什么是3層架構(gòu)?3層架構(gòu)的優(yōu)點(diǎn)是什么?
什么是3層架構(gòu)?
3層架構(gòu)是一種“客戶端-服務(wù)器”架構(gòu),在此架構(gòu)中用戶接口,商業(yè)邏輯,數(shù)據(jù)保存以及數(shù)據(jù)訪問被設(shè)計(jì)為獨(dú)立的模塊。主要有3個(gè)層面,第一層(表現(xiàn)層,gui層),第二層(商業(yè)對(duì)象,商業(yè)邏輯層),第三層(數(shù)據(jù)訪問層)。這些層可以單獨(dú)開發(fā),單獨(dú)測試。
為什么要把程序代碼分為3層,把用戶接口層,商業(yè)邏輯層,數(shù)據(jù)訪問層分離有許多的優(yōu)點(diǎn)。
在快速開發(fā)中重用商業(yè)邏輯組件,我們已經(jīng)在系統(tǒng)中實(shí)現(xiàn)添加,更新,刪除,查找客戶數(shù)據(jù)的組件。這個(gè)組件已經(jīng)開發(fā)并且測試通過,我們可以在其他要保存客戶數(shù)據(jù)的項(xiàng)目中使用這個(gè)組件。
系統(tǒng)比較容易遷移,商業(yè)邏輯層與數(shù)據(jù)訪問層是分離的,修改數(shù)據(jù)訪問層不會(huì)影響到商業(yè)邏輯層。系統(tǒng)如果從用sql server存儲(chǔ)數(shù)據(jù)遷移到用oracle存儲(chǔ)數(shù)據(jù),并不需要修改商業(yè)邏輯層組件和gui組件
系統(tǒng)容易修改,假如在商業(yè)層有一個(gè)小小的修改,我們不需要在用戶的機(jī)器上重裝整個(gè)系統(tǒng)。我們只需要更新商業(yè)邏輯組件就可以了。
應(yīng)用程序開發(fā)人員可以并行,獨(dú)立的開發(fā)單獨(dú)的層。
代碼
這個(gè)組件有3層,第一個(gè)層或者稱為gui層用form實(shí)現(xiàn),叫做frmgui。第二層或者稱為商業(yè)邏輯層,叫做bocustomer,是bussniess object customer的縮寫。最后是第三層或者稱為數(shù)據(jù)層,叫做dacustomer,是data access customer的縮寫。為了方便我把三個(gè)層編譯到一個(gè)項(xiàng)目中。
用戶接口層
下面是用戶接口成的一段代碼,我只選取了調(diào)用商業(yè)邏輯層的一部分代碼。
//this function get the details from the user via gui
//tier and calls the add method of business logic layer.
private void cmdadd_click(object sender, system.eventargs e)
{
try
{
cus = new bocustomer();
cus.cusid=txtid.text.tostring();
cus.lname = txtlname.text.tostring();
cus.fname = txtfname.text.tostring();
cus.tel= txttel.text.tostring();
cus.address = txtaddress.text.tostring();
cus.add();
}
catch(exception err)
{
messagebox.show(err.message.tostring());
}
}
//this function gets the id from the user and finds the
//customer details and return the details in the form of
//a dataset via busniss object layer. then it loops through
//the content of the dataset and fills the controls.
private void cmdfind_click(object sender, system.eventargs e)
{
try
{
string cusid = txtid.text.tostring();
bocustomer thiscus = new bocustomer();
dataset ds = thiscus.find(cusid);
datarow row;
row = ds.tables[0].rows[0];
//via looping
foreach(datarow rows in ds.tables[0].rows )
{
txtfname.text = rows["cus_f_name"].tostring();
txtlname.text = rows["cus_l_name"].tostring();
txtaddress.text = rows["cus_address"].tostring();
txttel.text = rows["cus_tel"].tostring();
}
}
catch (exception err)
{
messagebox.show(err.message.tostring());
}
}
//this function used to update the customer details.
private void cmdupdate_click(object sender,
system.eventargs e)
{
try
{
cus = new bocustomer();
cus.cusid=txtid.text.tostring();
cus.lname = txtlname.text.tostring();
cus.fname = txtfname.text.tostring();
cus.tel= txttel.text.tostring();
cus.address = txtaddress.text.tostring();
cus.update();
}
catch(exception err)
{
messagebox.show(err.message.tostring());
}
}
商業(yè)邏輯層
下面是商業(yè)邏輯層的所有代碼,主要包括定義customer對(duì)象的屬性。但這僅僅是個(gè)虛構(gòu)的customer對(duì)象,如果需要可以加入其他的屬性。商業(yè)邏輯層還包括添加,更新,查找,等方法。
商業(yè)邏輯層是一個(gè)中間層,處于gui層和數(shù)據(jù)訪問層中間。他有一個(gè)指向數(shù)據(jù)訪問層的引用cusdata = new dacustomer().而且還引用了system.data名字空間。商業(yè)邏輯層使用dataset返回?cái)?shù)據(jù)給gui層。
using system;
using system.data;
namespace _3tierarchitecture
{
/// <summary>
/// summary description for bocustomer.
/// </summary>
public class bocustomer
{
//customer properties
private string fname;
private string lname;
private string cusid;
private string address;
private string tel;
private dacustomer cusdata;
public bocustomer()
{
//an instance of the data access layer!
cusdata = new dacustomer();
}
/// <summary>
/// property firstname (string)
/// </summary>
public string fname
{
get
{
return this.fname;
}
set
{
try
{
this.fname = value;
if (this.fname == "")
{
throw new exception(
"please provide first name ...");
}
}
catch(exception e)
{
throw new exception(e.message.tostring());
}
}
}
/// <summary>
/// property lastname (string)
/// </summary>
public string lname
{
get
{
return this.lname;
}
set
{
//could be more checkings here eg revmove ' chars
//change to proper case
//blah blah
this.lname = value;
if (this.lname == "")
{
throw new exception("please provide name ...");
}
}
}
/// <summary>
/// property customer id (string)
/// </summary>
public string cusid
{
get
{
return this.cusid;
}
set
{
this.cusid = value;
if (this.cusid == "")
{
throw new exception("please provide id ...");
}
}
}
/// <summary>
/// property address (string)
/// </summary>
public string address
{
get
{
return this.address;
}
set
{
this.address = value;
if (this.address == "")
{
throw new exception("please provide address ...");
}
}
}
/// <summary>
/// property telephone (string)
/// </summary>
public string tel
{
get
{
return this.tel;
}
set
{
this.tel = value;
if (this.tel == "")
{
throw new exception("please provide tel ...");
}
}
}
/// <summary>
/// function add new customer. calls
/// the function in data layer.
/// </summary>
public void add()
{
cusdata.add(this);
}
/// <summary>
/// function update customer details.
/// calls the function in data layer.
/// </summary>
public void update()
{
cusdata.update(this);
}
/// <summary>
/// function find customer. calls the
/// function in data layer.
/// it returns the details of the customer using
/// customer id via a dataset to gui tier.
/// </summary>
public dataset find(string str)
{
if (str == "")
throw new exception("please provide id to search");
dataset data = null;
data = cusdata.find(str);
return data;
}
}
}
數(shù)據(jù)訪問層
數(shù)據(jù)層包括處理ms access數(shù)據(jù)庫的細(xì)節(jié)。所有這些細(xì)節(jié)都是透明的,不會(huì)影響到商業(yè)邏輯層。數(shù)據(jù)訪問層有個(gè)指向商業(yè)邏輯層的引用bocustomer cus。為了應(yīng)用方便并且支持其他數(shù)據(jù)庫。
using system;
using system.data.oledb;
using system.data;
namespace _3tierarchitecture
{
/// <summary>
/// summary description for dacustomer.
/// </summary>
public class dacustomer
{
private oledbconnection cnn;
//change connection string as per the
//folder you unzip the files
private const string cnnstr =
"provider=microsoft.jet.oledb.4.0;data " +
"source= d://rahman_backup//programming//" +
"csharp//3tierarchitecture//customer.mdb;";
//local variables
private string strtable="";
private string strfields="";
private string strvalues="";
private string insertstr="";
//this needs to be changed based on customer
//table fields' name of the database!
private const string thistable = "tblcustomer";
private const string cus_id = "cus_id";
private const string cus_lname = "cus_l_name";
private const string cus_fname = "cus_f_name";
private const string cus_tel = "cus_tel";
private const string cus_address = "cus_address";
public dacustomer()
{
}
public dacustomer(bocustomer cus)
{
// a reference of the business object class
}
//standard dataset function that adds a new customer
public void add(bocustomer cus)
{
string str = buildaddstring(cus);
opencnn();
//open command option - cnn parameter is imporant
oledbcommand cmd = new oledbcommand(str,cnn);
//execute connection
cmd.executenonquery();
// close connection
closecnn();
}
//standard dataset function that updates
//details of a customer based on id
public void update(bocustomer cus)
{
opencnn();
string selectstr = "update " + thistable +
" set " + cus_lname + " = '" + cus.lname + "'" +
", " + cus_fname + " = '" + cus.fname + "'" +
", " + cus_address + " = '" + cus.address + "'" +
", " + cus_tel + " = '" + cus.tel + "'" +
" where cus_id = '" + cus.cusid + "'";
oledbcommand cmd = new oledbcommand(selectstr,cnn);
cmd.executenonquery();
closecnn();
}
//standard dataset function that finds and
//return the detail of a customer in a dataset
public dataset find(string argstr)
{
dataset ds=null;
try
{
opencnn();
string selectstr = "select * from " + thistable +
" where cus_id = '" + argstr + "'";
oledbdataadapter da =
new oledbdataadapter(selectstr,cnn);
ds = new dataset();
da.fill(ds,thistable);
closecnn();
}
catch(exception e)
{
string str = e.message;
}
return ds;
}
private void opencnn()
{
// initialise connection
string cnnstr = cnnstr;
cnn = new oledbconnection(cnnstr);
// open connection
cnn.open();
}
private void closecnn()
{
// 5- step five
cnn.close();
}
// just a supporting function that builds
// and return the insert string for dataset.
private string buildaddstring(bocustomer cus)
{
// these are the constants as
// set in the top of this module.
strtable="insert into " + thistable;
strfields=" (" + cus_id +
"," + cus_lname +
"," + cus_fname +
"," + cus_address +
"," + cus_tel + ")";
//these are the attributes of the
//customer business object.
strvalues= " values ( '" + cus.cusid +
"' , '" + cus.lname +
"' , '" + cus.fname +
"' , '" + cus.address +
"' , '" + cus.tel + "' )";
insertstr = strtable + strfields + strvalues;
return insertstr;
}
}
}
新聞熱點(diǎn)
疑難解答
圖片精選