不知道可能稱的上是ORM,其實就是一個DBHelper。看到網上不少人寫自己的ORM,但我覺得都不太好。 我這個ORM,學習成本非常低,常用的方法僅有幾個,在使用的過程中,你不需要有太多要註意的地方,也不會有“我怎樣實現連表查詢”的疑問。反射犧牲一些性能,但是降低了實現和使用的複雜度。 支持Orac ...
不知道可能稱的上是ORM,其實就是一個DBHelper。看到網上不少人寫自己的ORM,但我覺得都不太好。
我這個ORM,學習成本非常低,常用的方法僅有幾個,在使用的過程中,你不需要有太多要註意的地方,也不會有“我怎樣實現連表查詢”的疑問。反射犧牲一些性能,但是降低了實現和使用的複雜度。
支持Oracle、MSSQL、MySQL、SQLite四種資料庫,並配有Model生成器。
Model層的設計:
Models目錄中的類及其屬性和資料庫中的表和欄位是完全對應的,Models全部由生成器生成,並且不允許手動修改。ExtModels目錄中的類是擴展類,主要用於查詢與顯示,比如表中存的是code,但你需要關聯查詢另一張表中的name,就可以在這個擴展類中擴展一個用於顯示的name欄位。Models和ExtModels目錄的中類都是partial修飾。
例(由於是SQLite資料庫,所以生成的Model沒有註釋,其它三種資料庫有註釋):
Model:
using System; using System.Collections.Generic; using System.Linq; namespace Models { /// <summary> /// /// </summary> [Serializable] public partial class BS_Template { /// <summary> /// /// </summary> [IsId] [IsDBField] public string id { get; set; } /// <summary> /// /// </summary> [IsDBField] public string typeCode { get; set; } /// <summary> /// /// </summary> [IsDBField] public string type { get; set; } /// <summary> /// /// </summary> [IsDBField] public string code { get; set; } /// <summary> /// /// </summary> [IsDBField] public string name { get; set; } /// <summary> /// /// </summary> [IsDBField] public string path { get; set; } /// <summary> /// /// </summary> [IsDBField] public string folder { get; set; } /// <summary> /// /// </summary> [IsDBField] public string remarks { get; set; } } }View Code
ExtModel:
using System; using System.Collections.Generic; using System.Linq; namespace Models { /// <summary> /// /// </summary> public partial class BS_Template { //暫沒有擴展欄位 } }View Code
DBHelper代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.Objects.DataClasses; using System.Data.OracleClient; using System.Data.SqlClient; using System.Data.SQLite; using System.Reflection; using System.Text; using Models; using MySql.Data.MySqlClient; namespace DBUtil { /// <summary> /// 資料庫操作類 /// 2016年09月09日 /// </summary> public class DBHelper { #region 變數 /// <summary> /// 資料庫類型 /// </summary> private static string m_DBType = ConfigurationManager.AppSettings["DBType"]; /// <summary> /// 資料庫類型 /// </summary> private static bool m_AutoIncrement = ConfigurationManager.AppSettings["AutoIncrement"].ToLower() == "true" ? true : false; /// <summary> /// 資料庫連接字元串 /// </summary> private static string m_ConnectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString(); /// <summary> /// 事務 /// </summary> [ThreadStatic] private static DbTransaction m_Tran; /// <summary> /// 帶參數的SQL插入和修改語句中,參數前面的符號 /// </summary> private static string m_ParameterMark = GetParameterMark(); #endregion #region 構造函數 /// <summary> /// 資料庫操作類 /// </summary> public DBHelper() { } #endregion #region 生成變數 #region 生成 IDbCommand /// <summary> /// 生成 IDbCommand /// </summary> private DbCommand GetCommand() { DbCommand command = null; switch (m_DBType) { case "oracle": command = new OracleCommand(); break; case "mssql": command = new SqlCommand(); break; case "mysql": command = new MySqlCommand(); break; case "sqlite": command = new SQLiteCommand(); break; } return command; } /// <summary> /// 生成 IDbCommand /// </summary> private DbCommand GetCommand(string sql, DbConnection conn) { DbCommand command = null; switch (m_DBType) { case "oracle": command = new OracleCommand(sql); command.Connection = conn; break; case "mssql": command = new SqlCommand(sql); command.Connection = conn; break; case "mysql": command = new MySqlCommand(sql); command.Connection = conn; break; case "sqlite": command = new SQLiteCommand(sql); command.Connection = conn; break; } return command; } #endregion #region 生成 IDbConnection /// <summary> /// 生成 IDbConnection /// </summary> private static DbConnection GetConnection() { DbConnection conn = null; switch (m_DBType) { case "oracle": conn = new OracleConnection(m_ConnectionString); break; case "mssql": conn = new SqlConnection(m_ConnectionString); break; case "mysql": conn = new MySqlConnection(m_ConnectionString); break; case "sqlite": conn = new SQLiteConnection(m_ConnectionString); break; } return conn; } #endregion #region 生成 IDbDataAdapter /// <summary> /// 生成 IDbDataAdapter /// </summary> private DbDataAdapter GetDataAdapter(DbCommand cmd) { DbDataAdapter dataAdapter = null; switch (m_DBType) { case "oracle": dataAdapter = new OracleDataAdapter(); dataAdapter.SelectCommand = cmd; break; case "mssql": dataAdapter = new SqlDataAdapter(); dataAdapter.SelectCommand = cmd; break; case "mysql": dataAdapter = new MySqlDataAdapter(); dataAdapter.SelectCommand = cmd; break; case "sqlite": dataAdapter = new SQLiteDataAdapter(); dataAdapter.SelectCommand = cmd; break; } return dataAdapter; } #endregion #region 生成 m_ParameterMark /// <summary> /// 生成 m_ParameterMark /// </summary> private static string GetParameterMark() { switch (m_DBType) { case "oracle": return ":"; case "mssql": return "@"; case "mysql": return "@"; case "sqlite": return ":"; } return ":"; } #endregion #endregion #region 基礎方法 #region 執行簡單SQL語句 #region Exists public bool Exists(string sqlString) { using (DbConnection conn = GetConnection()) { using (DbCommand cmd = GetCommand(sqlString, conn)) { try { conn.Open(); object obj = cmd.ExecuteScalar(); if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) { return false; } else { return true; } } catch (Exception ex) { throw ex; } finally { cmd.Dispose(); conn.Close(); } } } } #endregion #region 執行SQL語句,返回影響的記錄數 /// <summary> /// 執行SQL語句,返回影響的記錄數 /// </summary> /// <param name="sqlString">SQL語句</param> /// <returns>影響的記錄數</returns> public int ExecuteSql(string sqlString) { DbConnection conn = m_Tran == null ? GetConnection() : m_Tran.Connection; using (DbCommand cmd = GetCommand(sqlString, conn)) { try { if (conn.State != ConnectionState.Open) conn.Open(); if (m_Tran != null) cmd.Transaction = m_Tran; int rows = cmd.ExecuteNonQuery(); return rows; } catch (Exception ex) { throw new Exception(ex.Message); } finally { cmd.Dispose(); if (m_Tran == null) conn.Close(); } } } #endregion #region 執行一條計算查詢結果語句,返回查詢結果 /// <summary> /// 執行一條計算查詢結果語句,返回查詢結果(object) /// </summary> /// <param name="sqlString">計算查詢結果語句</param> /// <returns>查詢結果(object)</returns> public object GetSingle(string sqlString) { using (DbConnection conn = GetConnection()) { using (DbCommand cmd = GetCommand(sqlString, conn)) { try { if (conn.State != ConnectionState.Open) conn.Open(); object obj = cmd.ExecuteScalar(); if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) { return null; } else { return obj; } } catch (Exception ex) { throw ex; } finally { cmd.Dispose(); } } } } #endregion #region 執行查詢語句,返回IDataReader /// <summary> /// 執行查詢語句,返回IDataReader ( 註意:調用該方法後,一定要對IDataReader進行Close ) /// </summary> /// <param name="sqlString">查詢語句</param> /// <returns>IDataReader</returns> public DbDataReader ExecuteReader(string sqlString) { DbConnection conn = GetConnection(); DbCommand cmd = GetCommand(sqlString, conn); try { if (conn.State != ConnectionState.Open) conn.Open(); DbDataReader myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return myReader; } catch (Exception ex) { throw ex; } } #endregion #region 執行查詢語句,返回DataSet /// <summary> /// 執行查詢語句,返回DataSet /// </summary> /// <param name="sqlString">查詢語句</param> /// <returns>DataSet</returns> public DataSet Query(string sqlString) { using (DbConnection conn = GetConnection()) { DataSet ds = new DataSet(); try { conn.Open(); using (DbCommand cmd = GetCommand(sqlString, conn)) { DbDataAdapter adapter = GetDataAdapter(cmd); adapter.Fill(ds, "ds"); } } catch (Exception ex) { throw ex; } finally { conn.Close(); } return ds; } } #endregion #endregion #region 執行帶參數的SQL語句 #region 執行SQL語句,返回影響的記錄數 /// <summary> /// 執行SQL語句,返回影響的記錄數 /// </summary> /// <param name="SQLString">SQL語句</param> /// <returns>影響的記錄數</returns> public int ExecuteSql(string SQLString, params DbParameter[] cmdParms) { DbConnection conn = m_Tran == null ? GetConnection() : m_Tran.Connection; using (DbCommand cmd = GetCommand()) { try { PrepareCommand(cmd, conn, m_Tran, SQLString, cmdParms); int rows = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return rows; } catch (Exception ex) { throw ex; } finally { cmd.Dispose(); if (m_Tran == null) conn.Close(); } } } #endregion #region 執行查詢語句,返回IDataReader /// <summary> /// 執行查詢語句,返回IDataReader ( 註意:調用該方法後,一定要對IDataReader進行Close ) /// </summary> /// <param name="strSQL">查詢語句</param> /// <returns>IDataReader</returns> public DbDataReader ExecuteReader(string sqlString, params DbParameter[] cmdParms) { DbConnection conn = GetConnection(); DbCommand cmd = GetCommand(); try { PrepareCommand(cmd, conn, null, sqlString, cmdParms); DbDataReader myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); cmd.Parameters.Clear(); return myReader; } catch (Exception ex) { throw ex; } } #endregion #region 執行查詢語句,返回DataSet /// <summary> /// 執行查詢語句,返回DataSet /// </summary> /// <param name="sqlString">查詢語句</param> /// <returns>DataSet</returns> public DataSet Query(string sqlString, params DbParameter[] cmdParms) { DbConnection conn = GetConnection(); DbCommand cmd = GetCommand(); PrepareCommand(cmd, conn, null, sqlString, cmdParms); using (DbDataAdapter da = GetDataAdapter(cmd)) { DataSet ds = new DataSet(); try { da.Fill(ds, "ds"); cmd.Parameters.Clear(); } catch (Exception ex) { throw ex; } finally { cmd.Dispose(); conn.Close(); } return ds; } } #endregion #region PrepareCommand private void PrepareCommand(DbCommand cmd, DbConnection conn, DbTransaction trans, string cmdText, DbParameter[] cmdParms) { if (conn.State != ConnectionState.Open) conn.Open(); cmd.Connection = conn; cmd.CommandText = cmdText; if (trans != null) cmd.Transaction = trans; cmd.CommandType = CommandType.Text; if (cmdParms != null) { foreach (DbParameter parm in cmdParms) { cmd.Parameters.Add(parm); } } } #endregion #endregion #endregion #region 增刪改查 #region 獲取最大編號 /// <summary> /// 獲取最大編號 /// </summary> /// <typeparam name="T">實體Model</typeparam> /// <param name="key">主鍵</param> public int GetMaxID<T>(string key) { Type type = typeof(T); string sql = null; switch (m_DBType) { case "oracle": sql = string.Format("SELECT Max({0}) FROM {1}", key, type.Name); break; case "mssql": sql = string.Format("SELECT Max({0}) FROM {1}", key, type.Name); break; case "mysql": sql = string.Format("SELECT Max({0}) FROM {1}", key, type.Name); break; case "sqlite": sql = string.Format("SELECT Max(cast({0} as int)) FROM {1}", key, type.Name); break; } using (DbConnection conn = GetConnection()) { using (IDbCommand cmd = GetCommand(sql, conn)) { try { conn.Open(); object obj = cmd.ExecuteScalar(); if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) { return 1; } else { return int.Parse(obj.ToString()) + 1; } } catch (Exception ex) { throw ex; } finally { cmd.Dispose(); conn.Close(); } } } } #endregion #region 添加 /// <summary> /// 添加 /// </summary> public void Insert(object obj) { Insert(obj, m_AutoIncrement); } /// <summary> /// 添加 /// </summary> public void Insert(object obj, bool autoIncrement) { StringBuilder strSql = new StringBuilder(); Type type = obj.GetType(); strSql.Append(string.Format("insert into {0}(", type.Name)); PropertyInfo[] propertyInfoList = GetEntityProperties(type); List<string> propertyNameList = new List<string>(); int savedCount = 0; foreach (PropertyInfo propertyInfo in propertyInfoList) { if (propertyInfo.GetCustomAttributes(typeof(IsIdAttribute), false).Length > 0 && autoIncrement) return; if (propertyInfo.GetCustomAttributes(typeof(IsDBFieldAttribute), false).Length > 0) { propertyNameList.Add(propertyInfo.Name); savedCount++; } } strSql.Append(string.Format("{0})", string.Join(",", propertyNameList.ToArray()))); strSql.Append(string.Format(" values ({0})", string.Join(",", propertyNameList.ConvertAll<string>(a => m_ParameterMark + a).ToArray()))); SQLiteParameter[] parameters = new SQLiteParameter[savedCount]; int k = 0; for (int i = 0; i < propertyInfoList.Length && savedCount > 0; i++) { PropertyInfo propertyInfo = propertyInfoList[i]; if (propertyInfo.GetCustomAttributes(typeof(IsIdAttribute), false).Length > 0 && autoIncrement) return; if (propertyInfo.GetCustomAttributes(typeof(IsDBFieldAttribute), false).Length > 0) { object val = propertyInfo.GetValue(obj, null); SQLiteParameter param = new SQLiteParameter(m_ParameterMark + propertyInfo.Name, val == null ? DBNull.Value : val); parameters[k++] = param; } } ExecuteSql(strSql.ToString(), parameters); } #endregion #region 修改 /// <summary> /// 修改 /// </summary> public void Update(object obj) { object oldObj = Find(obj, false); if (oldObj == null) throw new Exception("無法獲取到舊數據"); StringBuilder strSql = new