偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

如何打造自己的數(shù)據(jù)訪問層二

數(shù)據(jù)庫
當(dāng)我們已了解了.NET對(duì)數(shù)據(jù)庫操作的基本原理,只需要兩個(gè)基本對(duì)象,就可以形成簡單的數(shù)據(jù)訪問層了。

當(dāng)我們通過上篇《打造自己的數(shù)據(jù)訪問層一》已了解了.NET對(duì)數(shù)據(jù)庫操作的基本原理,并就Ado.net對(duì)象的使用提出了幾點(diǎn)疑問:

1、如何由系統(tǒng)來判斷數(shù)據(jù)庫型。

2、如何消除這些重復(fù)代碼。

而上篇中也提出了一種解決思路,對(duì)ADO.NET對(duì)象進(jìn)行封裝,具體應(yīng)該如何實(shí)施?

1、需要一個(gè)對(duì)象,該對(duì)象用于建立內(nèi)存表與物理表的之間映射關(guān)系,解決數(shù)據(jù)查詢、更新操作,形成了數(shù)據(jù)映射對(duì)象,定義為DataMapping。

2、每一個(gè)映射對(duì)象只與一張物理建立映射關(guān)系,如果有多個(gè)這樣的對(duì)象同時(shí)操作,如何解決?這時(shí)就需要另一個(gè)對(duì)象,用于添加映射對(duì)象集合,打包映射對(duì)象操作,形成了數(shù)據(jù)執(zhí)行者,定義為DataExecutor。

想想看,只需要這兩個(gè)基本對(duì)象,就可以形成簡單的數(shù)據(jù)訪問層了。

先實(shí)現(xiàn)DataMapping,它應(yīng)具備如下功能。

1、需要知道物理表的信息,表名、主鍵集、字段集。

2、需要知道映射的是什么類型的數(shù)據(jù)庫,MSSql數(shù)據(jù)庫、Oracle數(shù)據(jù)庫、MySql數(shù)據(jù)庫或者其他類型的數(shù)據(jù)庫。

3、可查詢數(shù)據(jù),即填充內(nèi)存表。

4、可更新數(shù)據(jù),并且可設(shè)置更新操作方式。

5、可加入到事務(wù)中去。

根據(jù)上述功能,可初步設(shè)計(jì)出的DataMapping類:

public class DataMapping
{
public DataMapping()
{ }

/// <summary>
/// 填充數(shù)據(jù)集
/// </summary>
public void Fill()
{

}

/// <summary>
/// 設(shè)置更新命令
/// </summary>
public void SetCommands()
{

}

/// <summary>
/// 設(shè)置數(shù)據(jù)提交事務(wù)
/// </summary>
public void SetTransaction()
{

}

/// <summary>
/// 提交數(shù)據(jù)
/// </summary>
public bool Update()
{

}

/// <summary>
/// 更新列名
/// </summary>
public string Columns
{
get
{
return columns;
}
set
{
columns
= value;
}
}
private string columns = "";

/// <summary>
/// 主鍵名
/// </summary>
public string KeyColumns
{
get
{
return keyColumns;
}
set
{
keyColumns
= value;
}
}
private string keyColumns = "";

/// <summary>
/// 表名
/// </summary>
public string TableName
{
get
{
return tableName;
}
set
{
tableName
= value;
}
}
private string tableName = "";
}


再來實(shí)現(xiàn)DataExecutor類,它應(yīng)具備的功能:

1、應(yīng)該知道執(zhí)行什么類型的數(shù)據(jù)庫操作。

2、可以添加映射對(duì)象。

3、可以進(jìn)行數(shù)據(jù)提交。

如何來知道執(zhí)行的數(shù)據(jù)庫類型,我們可以定義具體的執(zhí)行者,比如MSSql執(zhí)行者、Oracle執(zhí)行者、MySql執(zhí)行者。

可以初步設(shè)計(jì)出DataExecutor類
 

public abstract class DataExecutor
{
private IList<DataMapping> lisDataMappings = new List<DataMapping>();

/// <summary>
/// 添加數(shù)據(jù)映射對(duì)象
/// </summary>
public void AddDataMapping(DataMapping map)
{

}

/// <summary>
/// 更新數(shù)據(jù)
/// </summary>
public bool Update()
{

}
}

public class MSSqlExecutor : DataExecutor
{

}

public class OracleExecutor : DataExecutor
{

}

public class MySqlExecutor : DataExecutor
{

}


準(zhǔn)備就緒,開始行具體設(shè)計(jì)。

先從DataMapping的Fill方法入手,看看它是如何查詢數(shù)據(jù)的。

public void Fill(string sqlText, string tableName, DataSet ds)
{
IDbConnection conn
= 具體的數(shù)據(jù)連接對(duì)象;
IDbDataAdapter dataAdapter
= 具體的數(shù)據(jù)適配對(duì)象;
IDbCommand cmd
= 具體的命令對(duì)象;
cmd.Connection
= conn;
cmd.CommandText
= sqlText;
dataAdapter.SelectCommand
= cmd;
((DbDataAdapter)dataAdapter).Fill(ds, tableName);
}

問題出來了,這里出現(xiàn)了具體的對(duì)象,如何得到這些對(duì)象?

前面我們?cè)O(shè)計(jì)了MSSqlExecutor類,它已經(jīng)知道具體的數(shù)據(jù)庫類型,所以它也應(yīng)該知道進(jìn)行數(shù)據(jù)操作的具體的對(duì)象,DataMapping類是否可以引用該它,從而通過它來獲取數(shù)據(jù)操作對(duì)象,因此,可以MSSqlExecutor類及DataMapping類進(jìn)行修改,使DataMapping對(duì)MSSqlExecutor類產(chǎn)生依賴關(guān)系;這只是對(duì)MSSql數(shù)據(jù)庫進(jìn)行操作,現(xiàn)要改變數(shù)據(jù)庫對(duì)象為Oracle了,DataMapping類應(yīng)該也需要對(duì)OracleExecutor類產(chǎn)生依賴關(guān)系。

因此,這里可以設(shè)計(jì)一個(gè)接口,用于獲取具體對(duì)象:

/// <summary>
/// 映射執(zhí)行接口
/// </summary>
public interface IMappingExecute
{
/// <summary>
/// 獲取連接對(duì)象
/// </summary>
IDbConnection GetConn();

/// <summary>
/// 獲取數(shù)據(jù)適配器
/// </summary>
IDbDataAdapter GetDataAdapter();

/// <summary>
/// 獲取命令對(duì)象
/// </summary>
IDbCommand GetCommand();

/// <summary>
/// 獲取命令參數(shù)
/// </summary>
IDbDataParameter GetDataParameter(string col);

/// <summary>
/// 獲取命令參數(shù)
/// 數(shù)據(jù)庫之間的命令參類是不一樣的
/// MMSql是“@” + 列名,Oracle是 “:” + 列名,MySql是 “?” + 列名
/// </summary>
string GetSourceColumn(string col);
}

改造后的MSSqlExecutor類為:

public class MSSqlExecutor : DataExecutor, IMappingExecute
{
}

改造后的DataMapping類為:

public class DataMapping
{
private IDbConnection conn = null;
private IDbDataAdapter dataAdapter = null;

/// <summary>
/// 映射執(zhí)行對(duì)象
/// </summary>
public IMappingExecute ExecuteObject
{
set
{
executeObj
= value;
conn
= executeObj.GetConn();
}
}
private IMappingExecute executeObj;

/// <summary>
/// 填充數(shù)據(jù)集
/// 參數(shù):查詢語句
/// 參數(shù):內(nèi)存表名
/// </summary>
public void Fill(string sqlText, string tableName, DataSet ds)
{
dataAdapter
= executeObj.GetDataAdapter();
IDbCommand cmd
= executeObj.GetCommand();
cmd.Connection
= conn;
cmd.CommandText
= sqlText;
dataAdapter.SelectCommand
= cmd;
((DbDataAdapter)dataAdapter).Fill(ds, tableName);
}
}
到此為止,查詢功能算是完成了,接下來該實(shí)現(xiàn)更新功能了,從SetCommands入手,以新增操作為例:
 
/// <summary>
/// 設(shè)置更新命令
/// </summary>
public void SetCommands(DataCommandType commandType, DataSet ds)
{

if ((commandType & DataCommandType.Insert) == DataCommandType.Insert)
{
CreateInsertCommand(ds);
}

if ((commandType & DataCommandType.Update) == DataCommandType.Update)
{
CreateUpdateCommand(ds);
}

if ((commandType & DataCommandType.Delete) == DataCommandType.Delete)
{
CreateDeleteCommand(ds);
}
}


/// <summary>
/// 生成新增命令及SQL語句
/// </summary>
private void CreateInsertCommand(DataSet ds)
{
IList
<string> lisColumns = GetColumns(ds);
StringBuilder sbCol
= new StringBuilder();
StringBuilder sbVal
= new StringBuilder();
foreach (string col in lisColumns)
{
sbCol.AppendFormat(
", {0}", col);
sbVal.AppendFormat(
", {0}", executeObj.GetSourceColumn(col));
}

sbCol.Remove(
0, 2);
sbVal.Remove(
0, 2);
string sqlText = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, sbCol.ToString(), sbVal.ToString());
IDbCommand cmd
= executeObj.GetCommand();
cmd.Connection
= conn;
cmd.CommandText
= sqlText;
SetCommandParams(cmd, lisColumns);
dataAdapter.InsertCommand
= cmd;
}

/// <summary>
/// 獲取列字段集
/// </summary>
private IList<string> GetColumns(DataSet ds)
{
IList
<string> lisColumns = new List<string>();
if (columns != "*")
{
string[] sltCol = columns.Split(',');
foreach (string col in sltCol)
{
lisColumns.Add(col.Trim());
}
}
else
{
DataTable dt
= ds.Tables[tableName];
foreach (DataColumn dc in dt.Columns)
{
lisColumns.Add(dc.ColumnName);
}
}

return lisColumns;
}

 
更新操作非常簡單,就是在上一篇的數(shù)據(jù)操作原理的基礎(chǔ)上動(dòng)態(tài)生成了查詢語句及參數(shù)綁定,不多做解釋。 

其中DataCommandType為自定義枚舉類型:

/// <summary>
/// 數(shù)據(jù)操作命令類型
/// </summary>
public enum DataCommandType
{
/// <summary>
/// 新增
/// </summary>
Insert = 1,

/// <summary>
/// 修改
/// </summary>
Update = 2,

/// <summary>
/// 刪除
/// </summary>
Delete = 4
}

更新完后進(jìn)行數(shù)據(jù)提交:

/// <summary>
/// 提交數(shù)據(jù)
/// </summary>
public bool Update(DataSet ds)
{
return ((DbDataAdapter)dataAdapter).Update(ds, tableName) > 0;
}

至此,數(shù)據(jù)更新操作也已經(jīng)完成,***再看看數(shù)據(jù)執(zhí)行者是如何進(jìn)行批量提交。

這里產(chǎn)生的***個(gè)問題是,什么時(shí)候數(shù)據(jù)執(zhí)行者會(huì)人將映射對(duì)象加入到集合中來,其中一種方法是在DataMapping設(shè)置更新的時(shí)候自己加入到集合去。

因此, 映射執(zhí)行接口得多添加一個(gè)方法,用于新增映射對(duì)象:

/// <summary>
/// 添加數(shù)據(jù)映射對(duì)象
/// </summary>
void AddDataMapping(DataMapping map);
 
修改SetCommand方法:
/// <summary>
/// 設(shè)置更新命令
/// </summary>
public void SetCommands(DataCommandType commandType, DataSet ds)
{
//設(shè)置更新事件時(shí)添加映射對(duì)象
executeObj.AddDataMapping(this);
}
現(xiàn)在執(zhí)行者中已經(jīng)存在了,可以進(jìn)行***的數(shù)據(jù)提交:
/// <summary>
/// 更新數(shù)據(jù)
/// </summary>
public bool Update(DataSet ds)
{
using (conn)
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}

IDbTransaction transaction
= conn.BeginTransaction(IsolationLevel.ReadCommitted);
foreach (DataMapping map in lisDataMappings)
{
map.SetTransaction(transaction);
}

try
{
foreach (DataMapping map in lisDataMappings)
{
map.Update(ds);
}

transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw new System.Exception(ex.Message);
}
}

return true;
}

//DataMapping類設(shè)置事務(wù)
/// <summary>
/// 設(shè)置數(shù)據(jù)提交事務(wù)
/// </summary>
public void SetTransaction(IDbTransaction transaction)
{
if (dataAdapter.InsertCommand != null)
{
dataAdapter.InsertCommand.Transaction
= transaction;
}

if (dataAdapter.UpdateCommand != null)
{
dataAdapter.UpdateCommand.Transaction
= transaction;
}

if (dataAdapter.DeleteCommand != null)
{
dataAdapter.DeleteCommand.Transaction
= transaction;
}
}

 
到些為止,我們自己的數(shù)據(jù)訪問層功能已基本完成,但是,我們要如何對(duì)其進(jìn)行調(diào)用,現(xiàn)在的方式真能方便的讓我們進(jìn)行調(diào)用嗎?答案是否定的。
 

暫且至此為止,下一篇我們?cè)龠M(jìn)行***的收尾工作,并最終打造成符合自己需求的數(shù)據(jù)訪問層

 

原文鏈接:http://www.cnblogs.com/FlySoul/archive/2011/05/04/2036953.html

【編輯推薦】

  1. 曬曬我的通用數(shù)據(jù)訪問層
  2. 幾步走,教你創(chuàng)建簡單訪問數(shù)據(jù)庫方法
  3. 一句代碼實(shí)現(xiàn)批量數(shù)據(jù)綁定 下
  4. 一步一步設(shè)計(jì)你的數(shù)據(jù)庫1
  5. 不重復(fù)隨機(jī)數(shù)列生成算法
責(zé)任編輯:艾婧 來源: 博客園
相關(guān)推薦

2011-05-10 16:44:43

數(shù)據(jù)訪問層

2011-05-07 12:56:39

數(shù)據(jù)訪問

2010-03-17 16:19:28

Linux 常用應(yīng)用軟

2009-01-08 09:52:26

2011-03-29 09:15:28

通用數(shù)據(jù)訪問層

2025-01-26 17:00:46

2012-01-11 09:46:31

DAL

2009-08-13 14:59:00

C#數(shù)據(jù)訪問層

2016-02-15 14:13:39

Python編碼環(huán)境

2023-07-27 08:16:51

數(shù)據(jù)訪問層項(xiàng)目

2013-11-26 09:47:47

ORM

2009-08-04 10:17:55

ASP.NET SqlASP.NET數(shù)據(jù)訪問

2009-08-19 10:54:42

ASP.NET數(shù)據(jù)訪問

2009-09-04 18:00:54

C#數(shù)據(jù)訪問層

2012-06-07 10:53:08

架構(gòu)設(shè)計(jì)數(shù)據(jù)訪問層設(shè)計(jì)原則

2011-08-31 13:45:38

Demon CamipadiPhone

2020-12-14 08:09:03

弱口令工具掃描

2015-10-15 09:37:50

桌面環(huán)境發(fā)行版Linux

2011-04-27 11:04:37

2014-03-27 15:24:43

農(nóng)行大數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)