例如用戶表Users有三個字段:id(varchar2),name(Varchar2),age(number)。用戶理所當然要抽象成一個類(當然,這裏談的是面向對象設計),而該類的數據成員應該是Users表中的三個字段。至於用戶類的方法,總少不了增刪改查這些操作,例如添加新用戶,修改用戶信息,查詢用戶等等。
問題來了,如果我們有N個表,要對這N個表進行操作,寫N個類,他們的數據成員(其實就是數據表字段)不一樣,卻有着一些相同的方法(增刪改查),是不是要給每一個類一一地寫這些實現呢?如果N>10,你是否感覺很累呢?以後如果還有類似的項目,你又要重新再寫N個類,買噶的,我都要瘋了,不知道你有何感想?
我們是程序員,但不能傻傻的悶聲寫程序,那樣鍵盤敲破了都不會有進步。寫程序之前,想一想,我的代碼怎麼樣才能設計的更加精巧更加容易複用呢?
我在前面的博客中好像寫過利用抽象工廠模式實現不同數據庫的自由切換(?時間太長,不大記得了)。這裏再寫一個抽象的數據表數據實體類作爲基類,爲他的每個子類實現增刪改查這些數據庫操作,子類只要向基類傳入表名和列名就可以了。這樣,以後每個項目你都不用再染指關於數據庫的東西了。
首先是一個數據項類,該類把列名和數據綁定起來,方便操作。
- /// <summary>
- /// 數據項類 包括數據庫字段名稱和值
- /// </summary>
- public class DataItem
- {
- private static IDatabaseFactory m_fac = SqlHelper.CreateDatabaseFactory(); //這個數據庫抽象工廠,會在後面列出來
- private readonly string m_name;
- private object m_value;
- /// <summary>
- /// 構造 數據項實例
- /// </summary>
- /// <param name="name">數據庫字段名稱</param>
- public DataItem(string name)
- {
- this.m_name = name;
- }
- /// <summary>
- /// 獲取 數據庫字段名稱
- /// </summary>
- public string Name
- {
- get { return m_name; }
- }
- /// <summary>
- /// 獲取或設置 字段對應的值
- /// </summary>
- public object Value
- {
- get { return m_value; }
- set { m_value = value; }
- }
- /// <summary>
- /// 獲取 值在SQL語句中的字符串表示
- /// </summary>
- public string ValueSqlString
- {
- get
- {
- if (m_value == null)
- {
- return "null";
- }
- else if (m_value.GetType() == typeof(string))
- {
- return "'" + m_value.ToString().Replace("'","''") + "'";
- }
- else if (m_value.GetType() == typeof(int))
- {
- return m_value.ToString();
- }
- else if (m_value.GetType() == typeof(DateTime))
- {
- return m_fac.ToDBTimeString(Convert.ToDateTime(m_value));
- }
- else
- {
- return "null";
- }
- }
- }
- public override string ToString()
- {
- return m_name + "="+ValueSqlString;
- }
- }
- /// <summary>
- /// 與數據庫表緊密相關 的 實體類
- /// </summary>
- public class DataTableObject
- {
- protected readonly string m_tableName;
- protected DataItem m_key;
- protected IList<DataItem> m_col;
- /// <summary>
- /// 構造 一個數據表實體類
- /// </summary>
- /// <param name="tableName">表名</param>
- /// <param name="keyName">主鍵名</param>
- /// <param name="colName">列名</param>
- protected DataTableObject(string tableName,string keyName,params string[] colName)
- {
- m_col = new List<DataItem>();
- this.m_tableName = tableName;
- this.m_key = new DataItem(keyName);
- if (colName==null) return;
- foreach (string col in colName)
- {
- m_col.Add(new DataItem(col));
- }
- }
- /// <summary>
- /// 構造 一個數據表實體類
- /// </summary>
- /// <param name="key">主鍵值</param>
- /// <param name="tableName">表名</param>
- /// <param name="keyName">主鍵名</param>
- /// <param name="colName">列名</param>
- protected DataTableObject(object key,string tableName, string keyName,params string[] colName)
- :this(tableName,keyName,colName)
- {
- m_key.Value = key;
- }
- /// <summary>
- /// 獲取或設計 主鍵值
- /// </summary>
- public object Key
- {
- get
- {
- return m_key.Value;
- }
- set
- {
- this.m_key.Value = value;
- this.Load();
- }
- }
- /// <summary>
- /// 獲取 指定列值
- /// </summary>
- /// <param name="index">列索引 依照構造函數傳入的列順序 從0開始</param>
- /// <returns></returns>
- public object GetDataValue(int index)
- {
- if (index > m_col.Count - 1) return null;
- if (m_col[index].Value == null) this.Load();
- return m_col[index].Value;
- }
- /// <summary>
- /// 獲取 指定列值
- /// </summary>
- /// <param name="columnName">列名稱</param>
- /// <returns></returns>
- public object GetDataValue(string columnName)
- {
- foreach (DataItem di in m_col)
- {
- if (di.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase))
- {
- if (di.Value == null) this.Load();
- return di.Value;
- }
- }
- return null;
- }
- /// <summary>
- /// 設置 指定列值
- /// </summary>
- /// <param name="index">列索引 依照構造函數傳入的列順序 從0開始</param>
- /// <param name="value">新的列值</param>
- /// <returns>設置是否成功</returns>
- public bool SetDataValue(int index, object value)
- {
- if (index > m_col.Count - 1) return false;
- m_col[index].Value = value;
- return true;
- }
- /// <summary>
- /// 設置 指定列值
- /// </summary>
- /// <param name="columnName">列名</param>
- /// <param name="value">新的列值</param>
- /// <returns>設置是否成功</returns>
- public bool SetDataValue(string columnName, object value)
- {
- foreach (DataItem di in m_col)
- {
- if (di.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase))
- {
- di.Value = value;
- return true;
- }
- }
- return false ;
- }
- /// <summary>
- /// 根據主鍵值 重新從數據庫中加載數據
- /// </summary>
- /// <returns>加載是否成功</returns>
- public virtual bool Load()
- {
- if (m_key.Value == null)
- {
- Logger.LogText("不能讀取數據,主鍵值爲空.主鍵:"+m_key.Name);
- return false;
- }
- StringBuilder sbSql = new StringBuilder("select ");
- foreach (DataItem di in m_col)
- {
- sbSql.Append(di.Name);
- sbSql.Append(",");
- }
- int len = sbSql.Length;
- sbSql.Remove(len - 1, 1);
- sbSql.Append(" from ");
- sbSql.Append(m_tableName);
- sbSql.Append(" where ");
- sbSql.Append(m_key.Name);
- sbSql.Append("=");
- sbSql.Append(m_key.ValueSqlString);
- DataSet ds = SqlHelper.ExecuteQuery(sbSql.ToString());
- if (ds == null)
- {
- Logger.LogText("數據庫插入操作失敗.");
- return false;
- }
- if (ds.Tables[0].Rows.Count < 1)
- {
- ds.Dispose();
- return false;
- }
- int index = 0;
- DataRow dr = ds.Tables[0].Rows[0];
- foreach (DataItem di in m_col)
- {
- di.Value = dr[index++];
- }
- return true;
- }
- /// <summary>
- /// 將本條記錄插入數據庫
- /// </summary>
- /// <returns>插入是否成功</returns>
- public virtual bool Insert()
- {
- StringBuilder sbSql = new StringBuilder("insert into ");
- sbSql.Append(m_tableName);
- sbSql.Append(" (");
- foreach (DataItem di in m_col)
- {
- sbSql.Append(di.Name);
- sbSql.Append(",");
- }
- sbSql.Remove(sbSql.Length-1,1);
- sbSql.Append(") values (");
- foreach (DataItem di in m_col)
- {
- sbSql.Append(di.ValueSqlString);
- sbSql.Append(",");
- }
- sbSql.Remove(sbSql.Length - 1, 1);
- sbSql.Append(")");
- int result = SqlHelper.ExecuteNonQuery(sbSql.ToString());
- if(result>0)
- return true;
- return false;
- }
- /// <summary>
- /// 將本條記錄的更新 寫入數據庫
- /// </summary>
- /// <returns>更新是否成功</returns>
- public virtual bool Update()
- {
- StringBuilder sbSql = new StringBuilder("update ");
- sbSql.Append(m_tableName);
- sbSql.Append(" set ");
- foreach (DataItem di in m_col)
- {
- sbSql.Append(di.Name);
- sbSql.Append("=");
- sbSql.Append(di.ValueSqlString);
- sbSql.Append(",");
- }
- sbSql.Remove(sbSql.Length - 1, 1);
- sbSql.Append(" where ");
- sbSql.Append(m_key.Name);
- sbSql.Append("=");
- sbSql.Append(m_key.ValueSqlString);
- int result = SqlHelper.ExecuteNonQuery(sbSql.ToString());
- if (result > 0)
- return true;
- return false;
- }
- /// <summary>
- /// 將本條記錄從數據庫中刪除
- /// </summary>
- /// <returns>刪除是否成功</returns>
- public virtual bool Delete()
- {
- StringBuilder sbSql = new StringBuilder("delete from ");
- sbSql.Append(m_tableName);
- sbSql.Append(" where ");
- sbSql.Append(m_key.Name);
- sbSql.Append("=");
- sbSql.Append(m_key.ValueSqlString);
- int result = SqlHelper.ExecuteNonQuery(sbSql.ToString());
- if (result > 0)
- return true;
- return false;
- }
- /// <summary>
- /// 獲取 數據表中所有記錄的對象列表
- /// </summary>
- /// <param name="tabName">表名</param>
- /// <param name="keyName">主鍵名</param>
- /// <param name="colName">列名</param>
- /// <returns>數據表中所有記錄的對象列表</returns>
- protected static IList<DataTableObject> GetAll(string tabName,string keyName,params string[] colName)
- {
- IList<DataTableObject> list = new List<DataTableObject>();
- StringBuilder sbSql = new StringBuilder("select ");
- sbSql.Append(keyName);
- foreach(string name in colName)
- {
- sbSql.Append(",");
- sbSql.Append(name);
- }
- sbSql.Append(" from ");
- sbSql.Append(tabName);
- DataSet ds = SqlHelper.ExecuteQuery(sbSql.ToString());
- if (ds == null)
- {
- Logger.LogText("數據庫查詢操作失敗.");
- return null;
- }
- int len = colName.Length;
- foreach (DataRow dr in ds.Tables[0].Rows)
- {
- DataTableObject obj = new DataTableObject(tabName, keyName, colName);
- obj.Key = dr[0];
- for (int i = 0; i <len; i++)
- {
- obj.SetDataValue(i, dr[i+1]);
- }
- list.Add(obj);
- }
- return list;
- }
- }
- public class User:DataTableObject
- {
- private const string tabName = "Users";
- private const string keyName = "id";
- private static readonly string[] colName = { "name","age"};
- public User():base(tabName,keyName,colName) { }
- public User(int id) : base(id, tabName, keyName, colName) { }
- public int ID
- {
- get
- {
- if (base.Key == null) return -1;//出錯
- return Convert.ToInt32(base.Key);
- }
- set
- {
- base.Key = value;
- }
- }
- public string Name
- {
- get
- {
- if (base.GetDataValue(0) == null) base.Load(); //如果爲空則重新載入
- return base.GetDataValue(0).ToString();
- }
- set
- {
- base.GetDataValue(0) = value;
- }
- }
- public int Age
- {
- get
- {
- if (base.GetDataValue("age") == null) base.Load(); //如果爲空則重新載入
- return Convert.ToInt32(base.GetDataValue("age"));
- }
- set
- {
- base.GetDataValue("age") = value;
- }
- }
- //增刪改查操作均繼承自父類,此處不需要重寫,如有需要也可以重寫
- }
如果對前面的數據庫抽象工廠類感到疑惑,可以看看下面的兩個工廠類:
抽象工廠:
- /// <summary>
- /// 數據庫工廠接口
- /// </summary>
- public interface IDatabaseFactory
- {
- /// <summary>
- /// 獲取 數據庫連接實例
- /// </summary>
- /// <returns>連接實例</returns>
- IDbConnection GetConnection();
- /// <summary>
- /// 獲取 數據庫命令實例
- /// </summary>
- /// <returns>命令實例</returns>
- IDbCommand GetCommand();
- /// <summary>
- /// 獲取 數據適配器實例
- /// </summary>
- /// <returns>數據適配器實例</returns>
- IDbDataAdapter GetDataAdapter();
- /// <summary>
- /// 將指定時間轉換成SQL語句
- /// </summary>
- /// <param name="time">時間</param>
- /// <returns>SQL語句</returns>
- string ToDBTimeString(DateTime time);
- }
- /// <summary>
- /// Oracle數據庫相關對象 工廠(同一對象關於多線程不安全)
- /// </summary>
- public class OracleFactory:IDatabaseFactory
- {
- //數據庫連接字符串
- private readonly string m_strConn = Config.Instance.ConnenctionString;
- private IDbConnection m_conn;
- private IDbCommand m_cmd;
- private IDbDataAdapter m_adapter;
- /// <summary>
- /// 獲取 數據庫連接實例
- /// </summary>
- /// <returns>數據庫連接實例</returns>
- public IDbConnection GetConnection()
- {
- if (m_conn == null)
- {
- m_conn = new OracleConnection();
- m_conn.ConnectionString = m_strConn;
- }
- return m_conn;
- }
- /// <summary>
- /// 獲取 數據庫命令實例
- /// </summary>
- /// <returns>數據庫命令實例</returns>
- public IDbCommand GetCommand()
- {
- if (m_cmd == null)
- {
- m_cmd = new OracleCommand();
- }
- return m_cmd;
- }
- /// <summary>
- /// 獲取 數據庫數據適配器實例
- /// </summary>
- /// <returns>數據庫數據適配器實例</returns>
- public IDbDataAdapter GetDataAdapter()
- {
- if (m_adapter == null)
- m_adapter = new OracleDataAdapter();
- return m_adapter;
- }
- public string ToDBTimeString(DateTime time)
- {
- return String.Format("to_date('{0}','yyyy-mm-dd hh24:mi:ss')",time);
- }
- }
看了這麼多代碼,一定很暈吧,哈,可能是我的代碼寫的不夠完美,如果有什麼改進意見,請不吝賜教~