• 三层架构浅析


        

    “三层架构”中的三层是指:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)

    表现层:通俗讲就是展现给用户的界面,即用户在使用一个系统时候他的所见所得。

    位于最外层(最上层),离用户最近。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。

    业务逻辑层:针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。

    负责处理用户输入的信息,或者是将这些信息发送给数据访问层进行保存,或者是调用数据访问层中的函数再次读出这些数据。中间业务层也可以包括一些对“商业逻辑”描述代码在里面

    数据访问层:该层所做事务直接操作数据库,正对数据的增添、删除、修改、更新、查找。

    仅实现对数据的保存和读取操作。数据访问,可以访问数据库系统、二进制文件、文本文档或是XML文档

    

    优缺点:

        优点:

      1、开发人员可以只关注整个结构中的其中某一层;

      2、可以很容易的用新的实现来替换原有层次的实现;

      3、可以降低层与层之间的依赖;

      4、有利于标准化;

      5、利于各层逻辑的复用。

      缺点:

        1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

      2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

    简单的三层如下所示:

    数据访问层:DAL

    sqlhelp类:

    public class SqlHelp
    {
    private SqlConnection con;//连接对象
    private SqlCommand cmd;//操作对象
    private SqlDataAdapter sda;//适配器(填充和更新数据库的一组数据命令和一个数据库连接)
    private SqlDataReader reader;//读取行
    private DataSet ds;//数据集

    /// <summary>
    /// 初始化连接对象
    /// </summary>
    public void Connection()
    {
    try
    {
    con
    = new SqlConnection(SqlConn.Str);
    con.Open();
    }
    catch (Exception)
    {
    ///
    }
    }

    public int Command(string strsql)
    {
    try
    {
    Connection();
    //打开连接
    cmd = new SqlCommand(strsql, con);
    int count = cmd.ExecuteNonQuery();//返回受影响的行数
    return count;
    }
    catch (Exception)
    {
    return -1;
    }
    finally
    {
    con.Dispose();
    }
    }

    /// <summary>
    /// 返回一个数据集合
    /// </summary>
    /// <param name="strsql">数据库操作语句</param>
    /// <returns>数据集</returns>
    public DataSet ReturnDs(string strsql, string table)
    {
    try
    {
    Connection();
    sda
    = new SqlDataAdapter(strsql, con);
    ds
    = new DataSet();
    sda.Fill(ds, table);
    return ds;
    }
    catch (Exception)
    {
    return null;
    }
    finally
    {
    con.Dispose();
    }
    }

    /// <summary>
    /// 返回一个只进的读取流
    /// </summary>
    /// <param name="strsql">数据库操作语句</param>
    /// <returns>返回一行数据</returns>
    public SqlDataReader ReturnReader(string strsql)
    {
    try
    {
    Connection();
    cmd
    = new SqlCommand(strsql, con);
    reader
    = cmd.ExecuteReader();
    return reader;
    }
    catch (Exception)
    {
    return null;
    }
    finally
    {
    con.Dispose();
    }
    }
    }

    2.SqlConn类: 创建一个连接到数据库的类

    public class SqlConn
    {
    private static string str = "server =.;database=Finance;uid=sa;pwd=123";

    /// <summary>
    /// Sqlconn连接的属性Str
    /// </summary>
    public static string Str
    {
    get { return str; }
    set { str = value; }
    }
    }

    3.SqlAccess类:

    namespace SQLAccessDatabase
    {
    class AccessDB
    {
    private string dbAddress;
    private string sqlString;
    private SqlConnection con=null;

    public AccessDB(string dbAddress, string sqlString)
    {
    this.dbAddress = dbAddress;
    this.sqlString = sqlString;
    }

    /// <summary>
    /// 连接数据库
    /// </summary>
    private void Connect()
    {
    try
    {
    if (con == null) //单件模式
    con = new SqlConnection(this.dbAddress);
    con.Open();
    }
    catch
    {
    }
    }

    /// <summary>
    /// 对数据库进行操作
    /// </summary>
    /// <param name="strArray">字符串的参数</param>
    /// <returns>是否连接成功</returns>
    public bool ConnectDB(params string[] strArray)
    {
    try
    {
    Connect();

    SqlCommand cmd
    = new SqlCommand(this.sqlString, con);

    //取SQL语句中的参数进行赋值
    string[] sqlstr = this.sqlString.Split('@');
    int i = -1;
    string tempstr = "";
    foreach (string str in sqlstr)
    {
    i
    ++;
    if (i == 0)
    continue;
    tempstr
    = "@" + str.Remove(str.IndexOf(' '));
    cmd.Parameters.Add(tempstr, SqlDbType.VarChar).Value
    = strArray[i - 1];
    }

    //对SQL语句进行操作
    string s = sqlString.Remove(sqlString.IndexOf(' '));
    if (s == "select")
    {
    SqlDataReader reader
    = cmd.ExecuteReader();
    if (reader.Read())
    {
    return true;
    }
    }
    else if (s == "insert" || s == "update" || s == "delete")
    {
    int count = cmd.ExecuteNonQuery();
    if (count >= 1)
    {
    return true;
    }
    }
    return false;
    }
    catch
    {
    return false;
    }
    finally
    {
    con.Dispose();
    }
    }

    /// <summary>
    /// 无连接读取数据库
    /// </summary>
    /// <param name="tableName">获取表的名字</param>
    /// <returns>数据集合</returns>
    public DataSet GetTable(params string[] tableName)
    {
    try
    {
    Connect();

    SqlDataAdapter sda
    = new SqlDataAdapter(sqlString, con);

    DataSet ds
    = new DataSet();
    if (tableName.Length == 0)
    {
    sda.Fill(ds);
    }
    else
    {
    foreach (string str in tableName)
    sda.Fill(ds, str);
    }

    return ds;
    }
    catch
    {
    return null;
    }
    finally
    {
    con.Dispose();
    }
    }
    }

    public class SQLServer
    {
    public static string dbAddress = "server=.;database=Finance;uid=sa;pwd=123";
    }
    }

    4.DBHelper类(用于存储过程)

    public class DBHelper
    {
    /// <summary>
    /// 构建 SqlCommand 对象(用来返回一个结果集,而不是一个整数值)
    /// </summary>
    /// <param name="connection">数据库连接</param>
    /// <param name="storedProcName">存储过程名</param>
    /// <param name="parameters">存储过程参数</param>
    /// <returns>SqlCommand</returns>
    private static SqlCommand BuildQueryCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters)
    {
    SqlCommand command
    = new SqlCommand(storedProcName, connection);
    command.CommandType
    = CommandType.StoredProcedure;

    foreach (SqlParameter parameter in parameters)
    {
    if (parameter != null)
    {
    // 检查未分配值的输出参数,将其分配以DBNull.Value.
    if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) &&
    (parameter.Value
    == null))
    {
    parameter.Value
    = DBNull.Value;
    }
    command.Parameters.Add(parameter);
    }
    }

    return command;
    }

    /// <summary>
    /// 执行存储过程,返回SqlDataReader ( 注意:调用该方法后,一定要对SqlDataReader进行Close )
    /// </summary>
    /// <param name="storedProcName">存储过程名</param>
    /// <param name="parameters">存储过程参数</param>
    /// <returns>SqlDataReader</returns>
    public static SqlDataReader RunProcedure(string storedProcName, IDataParameter[] parameters)
    {
    SqlConnection connection
    = new SqlConnection(Config.ConStr);
    SqlDataReader returnReader;
    connection.Open();
    SqlCommand command
    = BuildQueryCommand(connection, storedProcName, parameters);
    command.CommandType
    = CommandType.StoredProcedure;
    returnReader
    = command.ExecuteReader(CommandBehavior.CloseConnection);
    return returnReader;

    }

    /// <summary>
    /// 执行存储过程,返回DataSet
    /// </summary>
    /// <param name="storedProcName">存储过程名</param>
    /// <param name="parameters">存储过程参数</param>
    /// <returns>SqlDataReader</returns>
    public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters,string resultTableName)
    {
    SqlConnection connection
    = new SqlConnection(Config.ConStr);

    SqlDataAdapter da
    = new SqlDataAdapter("",connection);

    SqlCommand command
    = BuildQueryCommand(connection, storedProcName, parameters);
    command.CommandType
    = CommandType.StoredProcedure;

    da.SelectCommand
    = command;

    DataSet ds
    = new DataSet();

    if (resultTableName.Trim() != "")
    da.Fill(ds, resultTableName.Trim());
    else
    da.Fill(ds);

    return ds;

    }

    /// <summary>
    /// 执行存储过程,返回SqlDataReader ( 注意:调用该方法后,一定要对SqlDataReader进行Close )
    /// </summary>
    /// <param name="storedProcName">存储过程名</param>
    /// <param name="parameters">存储过程参数</param>
    /// <returns>SqlDataReader</returns>
    public static SqlDataReader RunSQL(string storedProcName, IDataParameter[] parameters)
    {
    SqlConnection connection
    = new SqlConnection(Config.ConStr);
    SqlDataReader returnReader;
    connection.Open();
    SqlCommand command
    = BuildQueryCommand(connection, storedProcName, parameters);
    command.CommandType
    = CommandType.Text;
    returnReader
    = command.ExecuteReader(CommandBehavior.CloseConnection);
    return returnReader;

    }
    }

    业务逻辑层:BLL

    Operation类:

    #region 报销管理

    SqlHelp help
    = new SqlHelp();
    public bool ExpendAccountPopedom()
    {
    string sqlstr = string.Format("select * from Popedom_Employee inner join Popedom on Popedom_Employee.PopedomID=Popedom.PopedomID ,Employee where Popedom_Employee.EmployeeID={0} and PopedomName='{1}' and Employee.EmployeeID={2} and Grade like '{3}'", int.Parse(IDNumber.IdNumber), "报销管理", int.Parse(IDNumber.IdNumber), "%经理");
    AccessDB adb
    = new AccessDB(SQLServer.dbAddress, sqlstr);
    return adb.ConnectDB();
    }
    public DataSet Bind(string table)
    {
    string strsql = "select *from ExpendAccount";
    return RetrunnewDS(table, strsql);
    }
    //将表中的数据在textBox一一显示
    public DataSet ShowIntxt(string expendaccountid, string table)
    {
    string strsql = string.Format("select *from ExpendAccount where ExpendaccountID={0}", expendaccountid);
    return RetrunnewDS(table, strsql);
    }

    //提交报销申请
    public bool ExpendAccount(int expendPeopleid, string goodTag, string purpose, string beforePay, string expendSum)
    {
    string strsql = string.Format("insert into ExpendAccount (ExpendPeopleID,GoodsTag,ExpendaccountTime,GoodsPurpose,BeforePay,ExpendSum) values({0},'{1}','{2}','{3}','{4}','{5}')", expendPeopleid, goodTag, DateTime.Now.ToShortDateString(), purpose, beforePay, expendSum);
    return ReturnCount(strsql);
    }
    //审批报销申请
    public bool ExpendAccountExamin(string promiserstatu, string index)
    {
    string strsql = string.Format("update ExpendAccount set PromiserStatu='{0}',Promiserid={1} where ExpendAccountId={2}", promiserstatu, int.Parse(IDNumber.IdNumber), index);
    return ReturnCount(strsql);
    }
    #endregion

    #region 工资管理
    //将工资表中的数据一一读到txtBox中
    public DataSet ShowIntxtPay(string table, string employeeid)
    {
    string strsql = string.Format("select *from EmployeePay where EmployeeID={0}", employeeid);
    return RetrunnewDS(table, strsql);
    }
    //Bind显示工资表中数据
    public DataSet BindPay(string table)
    {
    string strsql = "select *from EmployeePay";
    return RetrunnewDS(table, strsql);
    }
    //更新工资表
    public bool EmployeePayUpdate(int id, string baspay, string perpay, string subsidy, string prize, string allpay, string perincome, string reallypay)
    {
    string strsql = string.Format
    (
    "update EmployeePay set EmployeeID={0},BasicPay='{1}',PerformancePay='{2}',Subsidy='{3}',Prize='{4}', AllPay ='{5}',PersonalIncometax='{6}',ReallyPay='{7}' where EmployeeID={0}", id, baspay, perpay, subsidy, prize, allpay, perincome, reallypay, id);
    return (ReturnCount(strsql));
    }
    //添加员工工资信息
    public bool EmployeePayAdd(int id, string baspay, string perpay, string subsidy, string prize, string allpay, string perincome, string reallypay)
    {
    string strsql = string.Format
    (
    "insert into EmployeePay ( EmployeeID,BasicPay,PerformancePay,Subsidy,Prize, AllPay,PersonalIncometax,ReallyPay ) values ({0},'{1}','{2}','{3}','{4}','{5}','{6}','{7}')", id, baspay, perpay, subsidy, prize, allpay, perincome, reallypay);
    return ReturnCount(strsql);
    }
    //删除员工工资信息
    public bool EmployeePayDel(int id)
    {
    string strsql = string.Format("delete from EmployeePay where EmployeeID={0}", id);
    return ReturnCount(strsql);
    }
    #endregion

    #region 方法
    //返回受影响行数
    private bool ReturnCount(string strsql)
    {
    int count = help.Command(strsql);
    if (count >= 1)
    {
    return true;
    }
    else
    return false;
    }
    //返回数据集
    private DataSet RetrunnewDS(string table, string strsql)
    {
    DataSet ds
    = help.ReturnDs(strsql, table);
    return ds;
    }
    #endregion

    UserLogin类:防注入式攻击

    public class UserLogin
    {
    public bool UseLogin(string name, string pwd)
    {
    string str = "server=.;database=Finance;uid=sa;pwd=123";
    using (SqlConnection con =new SqlConnection (str))
    {
    con.Open();
    string strsql = "select * from PersonInfo where employeeid=@employeeid and employeepwd=@employeepwd";
    SqlCommand cmd
    = new SqlCommand(strsql, con);
    cmd.Parameters.Add(
    "@employeeid",SqlDbType.VarChar).Value = name;
    cmd.Parameters.Add(
    "@employeepwd", SqlDbType.VarChar).Value = pwd;
    SqlDataReader reader
    = cmd.ExecuteReader();
    if (reader.Read())
    {
    return true;
    }
    else
    return false;
    }
    }

    SqlHelp help
    = new SqlHelp();
    #region 方法
    //返回受影响行数
    private bool ReturnCount(string strsql)
    {
    int count = help.Command(strsql);
    if (count >= 1)
    {
    return true;
    }
    else
    return false;
    }
    //返回数据集
    private DataSet RetrunnewDS(string table, string strsql)
    {
    DataSet ds
    = help.ReturnDs(strsql, table);
    return ds;
    }
    #endregion
    }

    以上DAL仅仅是针对SqlServer数据库,要想针对所有的数据库均有效,可用到工厂模式。

    下面是工厂模式封装的DAL针对多个数据库,而且既可以封装的SqlHelper不仅对简单的五大对象封装,而且还可以针对对存储过程的封装(就是将上面的DbHelper和SqlHelp结合起来用)

    下面以PetShop4.0为例讲解如下:

    DBUtility类:OracleHelper


    /// <summary>
    /// A helper class used to execute queries against an Oracle database
    /// </summary>
    public abstract class OracleHelper {

    // Read the connection strings from the configuration file
    public static readonly string ConnectionStringLocalTransaction = ConfigurationManager.ConnectionStrings["OraConnString1"].ConnectionString;
    public static readonly string ConnectionStringInventoryDistributedTransaction = ConfigurationManager.ConnectionStrings["OraConnString2"].ConnectionString;
    public static readonly string ConnectionStringOrderDistributedTransaction = ConfigurationManager.ConnectionStrings["OraConnString3"].ConnectionString;
    public static readonly string ConnectionStringProfile = ConfigurationManager.ConnectionStrings["OraProfileConnString"].ConnectionString;
    public static readonly string ConnectionStringMembership = ConfigurationManager.ConnectionStrings["OraMembershipConnString"].ConnectionString;

    //Create a hashtable for the parameter cached
    private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

    /// <summary>
    /// Execute a database query which does not include a select
    /// </summary>
    /// <param name="connString">Connection string to database</param>
    /// <param name="cmdType">Command type either stored procedure or SQL</param>
    /// <param name="cmdText">Acutall SQL Command</param>
    /// <param name="commandParameters">Parameters to bind to the command</param>
    /// <returns></returns>
    public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {
    // Create a new Oracle command
    OracleCommand cmd = new OracleCommand();

    //Create a connection
    using (OracleConnection connection = new OracleConnection(connectionString)) {

    //Prepare the command
    PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

    //Execute the command
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }
    }

    /// <summary>
    /// Execute an OracleCommand (that returns no resultset) against an existing database transaction
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="trans">an existing database transaction</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(OracleTransaction trans, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {
    OracleCommand cmd
    = new OracleCommand();
    PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// Execute an OracleCommand (that returns no resultset) against an existing database connection
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(OracleConnection connection, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {

    OracleCommand cmd
    = new OracleCommand();

    PrepareCommand(cmd, connection,
    null, cmdType, cmdText, commandParameters);
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// Execute a select query that will return a result set
    /// </summary>
    /// <param name="connString">Connection string</param>
    //// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns></returns>
    public static OracleDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {

    //Create the command and connection
    OracleCommand cmd = new OracleCommand();
    OracleConnection conn
    = new OracleConnection(connectionString);

    try {
    //Prepare the command to execute
    PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);

    //Execute the query, stating that the connection should close when the resulting datareader has been read
    OracleDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    cmd.Parameters.Clear();
    return rdr;

    }
    catch {

    //If an error occurs close the connection as the reader will not be used and we expect it to close the connection
    conn.Close();
    throw;
    }
    }

    /// <summary>
    /// Execute an OracleCommand that returns the first column of the first record against the database specified in the connection string
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="connectionString">a valid connection string for a SqlConnection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {
    OracleCommand cmd
    = new OracleCommand();

    using (OracleConnection conn = new OracleConnection(connectionString)) {
    PrepareCommand(cmd, conn,
    null, cmdType, cmdText, commandParameters);
    object val = cmd.ExecuteScalar();
    cmd.Parameters.Clear();
    return val;
    }
    }

    /// <summary>
    /// Execute a OracleCommand (that returns a 1x1 resultset) against the specified SqlTransaction
    /// using the provided parameters.
    /// </summary>
    /// <param name="transaction">A valid SqlTransaction</param>
    /// <param name="commandType">The CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">The stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">An array of OracleParamters used to execute the command</param>
    /// <returns>An object containing the value in the 1x1 resultset generated by the command</returns>
    public static object ExecuteScalar(OracleTransaction transaction, CommandType commandType, string commandText, params OracleParameter[] commandParameters) {
    if(transaction == null)
    throw new ArgumentNullException("transaction");
    if(transaction != null && transaction.Connection == null)
    throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");

    // Create a command and prepare it for execution
    OracleCommand cmd = new OracleCommand();

    PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters);

    // Execute the command & return the results
    object retval = cmd.ExecuteScalar();

    // Detach the SqlParameters from the command object, so they can be used again
    cmd.Parameters.Clear();
    return retval;
    }

    /// <summary>
    /// Execute an OracleCommand that returns the first column of the first record against an existing database connection
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// Object obj = ExecuteScalar(conn, CommandType.StoredProcedure, "PublishOrders", new OracleParameter(":prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or PL/SQL command</param>
    /// <param name="commandParameters">an array of OracleParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(OracleConnection connectionString, CommandType cmdType, string cmdText, params OracleParameter[] commandParameters) {
    OracleCommand cmd
    = new OracleCommand();

    PrepareCommand(cmd, connectionString,
    null, cmdType, cmdText, commandParameters);
    object val = cmd.ExecuteScalar();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// Add a set of parameters to the cached
    /// </summary>
    /// <param name="cacheKey">Key value to look up the parameters</param>
    /// <param name="commandParameters">Actual parameters to cached</param>
    public static void CacheParameters(string cacheKey, params OracleParameter[] commandParameters) {
    parmCache[cacheKey]
    = commandParameters;
    }

    /// <summary>
    /// Fetch parameters from the cache
    /// </summary>
    /// <param name="cacheKey">Key to look up the parameters</param>
    /// <returns></returns>
    public static OracleParameter[] GetCachedParameters(string cacheKey) {
    OracleParameter[] cachedParms
    = (OracleParameter[])parmCache[cacheKey];

    if (cachedParms == null)
    return null;

    // If the parameters are in the cache
    OracleParameter[] clonedParms = new OracleParameter[cachedParms.Length];

    // return a copy of the parameters
    for (int i = 0, j = cachedParms.Length; i < j; i++)
    clonedParms[i]
    = (OracleParameter)((ICloneable)cachedParms[i]).Clone();

    return clonedParms;
    }

    /// <summary>
    /// Internal function to prepare a command for execution by the database
    /// </summary>
    /// <param name="cmd">Existing command object</param>
    /// <param name="conn">Database connection object</param>
    /// <param name="trans">Optional transaction object</param>
    /// <param name="cmdType">Command type, e.g. stored procedure</param>
    /// <param name="cmdText">Command test</param>
    /// <param name="commandParameters">Parameters for the command</param>
    private static void PrepareCommand(OracleCommand cmd, OracleConnection conn, OracleTransaction trans, CommandType cmdType, string cmdText, OracleParameter[] commandParameters) {

    //Open the connection if required
    if (conn.State != ConnectionState.Open)
    conn.Open();

    //Set up the command
    cmd.Connection = conn;
    cmd.CommandText
    = cmdText;
    cmd.CommandType
    = cmdType;

    //Bind it to the transaction if it exists
    if (trans != null)
    cmd.Transaction
    = trans;

    // Bind the parameters passed in
    if (commandParameters != null) {
    foreach (OracleParameter parm in commandParameters)
    cmd.Parameters.Add(parm);
    }
    }

    /// <summary>
    /// Converter to use boolean data type with Oracle
    /// </summary>
    /// <param name="value">Value to convert</param>
    /// <returns></returns>
    public static string OraBit(bool value) {
    if(value)
    return "Y";
    else
    return "N";
    }

    /// <summary>
    /// Converter to use boolean data type with Oracle
    /// </summary>
    /// <param name="value">Value to convert</param>
    /// <returns></returns>
    public static bool OraBool(string value) {
    if(value.Equals("Y"))
    return true;
    else
    return false;
    }
    }

    SqlHelper类:

    /// <summary>
    /// The SqlHelper class is intended to encapsulate high performance,
    /// scalable best practices for common uses of SqlClient.
    /// </summary>
    public abstract class SqlHelper {

    //Database connection strings
    public static readonly string ConnectionStringLocalTransaction = ConfigurationManager.ConnectionStrings["SQLConnString1"].ConnectionString;
    public static readonly string ConnectionStringInventoryDistributedTransaction = ConfigurationManager.ConnectionStrings["SQLConnString2"].ConnectionString;
    public static readonly string ConnectionStringOrderDistributedTransaction = ConfigurationManager.ConnectionStrings["SQLConnString3"].ConnectionString;
    public static readonly string ConnectionStringProfile = ConfigurationManager.ConnectionStrings["SQLProfileConnString"].ConnectionString;

    // Hashtable to store cached parameters
    private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

    /// <summary>
    /// Execute a SqlCommand (that returns no resultset) against the database specified in the connection string
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">a valid connection string for a SqlConnection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {

    SqlCommand cmd
    = new SqlCommand();

    using (SqlConnection conn = new SqlConnection(connectionString)) {
    PrepareCommand(cmd, conn,
    null, cmdType, cmdText, commandParameters);
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }
    }

    /// <summary>
    /// Execute a SqlCommand (that returns no resultset) against an existing database connection
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {

    SqlCommand cmd
    = new SqlCommand();

    PrepareCommand(cmd, connection,
    null, cmdType, cmdText, commandParameters);
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// Execute a SqlCommand (that returns no resultset) using an existing SQL Transaction
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="trans">an existing sql transaction</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>an int representing the number of rows affected by the command</returns>
    public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {
    SqlCommand cmd
    = new SqlCommand();
    PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
    int val = cmd.ExecuteNonQuery();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// Execute a SqlCommand that returns a resultset against the database specified in the connection string
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">a valid connection string for a SqlConnection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>A SqlDataReader containing the results</returns>
    public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {
    SqlCommand cmd
    = new SqlCommand();
    SqlConnection conn
    = new SqlConnection(connectionString);

    // we use a try/catch here because if the method throws an exception we want to
    // close the connection throw code, because no datareader will exist, hence the
    // commandBehaviour.CloseConnection will not work
    try {
    PrepareCommand(cmd, conn,
    null, cmdType, cmdText, commandParameters);
    SqlDataReader rdr
    = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    cmd.Parameters.Clear();
    return rdr;
    }
    catch {
    conn.Close();
    throw;
    }
    }

    /// <summary>
    /// Execute a SqlCommand that returns the first column of the first record against the database specified in the connection string
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="connectionString">a valid connection string for a SqlConnection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {
    SqlCommand cmd
    = new SqlCommand();

    using (SqlConnection connection = new SqlConnection(connectionString)) {
    PrepareCommand(cmd, connection,
    null, cmdType, cmdText, commandParameters);
    object val = cmd.ExecuteScalar();
    cmd.Parameters.Clear();
    return val;
    }
    }

    /// <summary>
    /// Execute a SqlCommand that returns the first column of the first record against an existing database connection
    /// using the provided parameters.
    /// </summary>
    /// <remarks>
    /// e.g.:
    /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
    /// </remarks>
    /// <param name="conn">an existing database connection</param>
    /// <param name="commandType">the CommandType (stored procedure, text, etc.)</param>
    /// <param name="commandText">the stored procedure name or T-SQL command</param>
    /// <param name="commandParameters">an array of SqlParamters used to execute the command</param>
    /// <returns>An object that should be converted to the expected type using Convert.To{Type}</returns>
    public static object ExecuteScalar(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters) {

    SqlCommand cmd
    = new SqlCommand();

    PrepareCommand(cmd, connection,
    null, cmdType, cmdText, commandParameters);
    object val = cmd.ExecuteScalar();
    cmd.Parameters.Clear();
    return val;
    }

    /// <summary>
    /// add parameter array to the cache
    /// </summary>
    /// <param name="cacheKey">Key to the parameter cache</param>
    /// <param name="cmdParms">an array of SqlParamters to be cached</param>
    public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters) {
    parmCache[cacheKey]
    = commandParameters;
    }

    /// <summary>
    /// Retrieve cached parameters
    /// </summary>
    /// <param name="cacheKey">key used to lookup parameters</param>
    /// <returns>Cached SqlParamters array</returns>
    public static SqlParameter[] GetCachedParameters(string cacheKey) {
    SqlParameter[] cachedParms
    = (SqlParameter[])parmCache[cacheKey];

    if (cachedParms == null)
    return null;

    SqlParameter[] clonedParms
    = new SqlParameter[cachedParms.Length];

    for (int i = 0, j = cachedParms.Length; i < j; i++)
    clonedParms[i]
    = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

    return clonedParms;
    }

    /// <summary>
    /// Prepare a command for execution
    /// </summary>
    /// <param name="cmd">SqlCommand object</param>
    /// <param name="conn">SqlConnection object</param>
    /// <param name="trans">SqlTransaction object</param>
    /// <param name="cmdType">Cmd type e.g. stored procedure or text</param>
    /// <param name="cmdText">Command text, e.g. Select * from Products</param>
    /// <param name="cmdParms">SqlParameters to use in the command</param>
    private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms) {

    if (conn.State != ConnectionState.Open)
    conn.Open();

    cmd.Connection
    = conn;
    cmd.CommandText
    = cmdText;

    if (trans != null)
    cmd.Transaction
    = trans;

    cmd.CommandType
    = cmdType;

    if (cmdParms != null) {
    foreach (SqlParameter parm in cmdParms)
    cmd.Parameters.Add(parm);
    }
    }
    }

     图片转自:http://www.cnblogs.com/terrydong/archive/2007/12/06/985722.html

    背景:

    由于目前服务的公司,系统复杂度很高,数据库使用了Oracle、SqlServer、MySql......(就差用到所有的数据库产品了,呵呵)

    系统重构的过程中,之前写的基于sqlserver的简单三层架构已经不能满足系统重构的需求...

    需求:

    支持多类型数据库

    操作多个同一类型数据库

    参考:

    PetShop4.0

    解决方案框架图如上图

    数据访问工具类

    数据访问类使用DbProviderFactory实现,方法在父类实现,子类中只需通过实现CreateInstance()方法来指定providerName和connectionString 即可,唯一遗憾的是Mysql数据库不能通过这种方式实现,需要再单独写数据访问类了。

    数据访问类 

     转载自:http://blog.sina.com.cn/s/blog_4a24068d01009mia.html

     工厂模式三层架构

    项目

    描述

    BLL

    商务逻辑层组件

    DALFactory

    用于定义要加载哪个数据库访问程序集的工厂类

    IDAL

    接口集合,需要被每一个DAL类具体实现

    Model

    业务实体模型

    SQLServerDAL

    SQL Server数据库的IDAL接口实现

    Web

    Web 页和用户控件

    BLL:调用接口实现数据层的访问,至于调用的是哪个数据类的实现,由DALFactory来实现.

    DALFactory:通过工厂模式来实现调用具体哪个的数据子层.通过读取读取web.config参数用反射机制来动态加载具体的程序集.

    IDAL:接口是一种系列‘功能’的声明或名单,接口没有实现细节,只是一些功能方法的定义.

    Model: 数据库是关系型,不是面向对象的,要实现面向对象那就得把平面的‘表’结合业务规则抽象成类.

    SQLServerDAL:是接口层的(SQLServer)实现,为了支持多数据库还可以有OracleDAL的实现.具体使用哪个由DALFactory决定.

    Common:项目所用的公共类库或组件。

    DBUtility:对ADO.NET数据访问封装的组件类库。

     

    简单三层结构

     

    项目

    描述

    BLL

    业务逻辑层

    Common

    通用类库组件

    DAL

    数据访问层

    DBUtility

    数据访问组件

    Web

    Web 页表示层

    Model

    业务实体模型

    BLL:调用接口实现数据层的访问,至于调用的是哪个数据类的实现,由DALFactory来实现.

    Common:项目所用的公共类库或组件。

    DBUtility:对ADO.NET数据访问封装的组件类库。

    Model: 数据库是关系型,不是面向对象的,要实现面向对象那就得把平面的‘表’结合业务规则抽象成类.

    DAL:是接口层的(SQLServer)实现,为了支持多数据库还可以有OracleDAL的实现.具体使用哪个由DALFactory决定.

     

    转载自:http://blog.csdn.net/xiaolukatie/archive/2009/04/01/4041109.aspx
    工厂模式则是属于一种设计模式,指的是专门定义一个类来负责创建其他类的实例,属于类的创建型模式,通常根据一个条件(参数)来返回不同的类的实例。

    以下是转自别人的观点,留待细看

    设计模式也是分类的

    三层模式是体系结构模式,MVC是设计模式

    三层模式又可归于部署模式,MVC可归于表示模式,工厂模式可归于分布式系统模式。

    三层模式跟工厂模式,个人的见解如下:

    工厂当然是得建立在三层的基础上的

    三层,简单的说,数据访问,业务逻辑,表示,3个层面,3层会在一定程度上降低效率

    但是他的优点远远的大于了那一点点的缺点,代码易于维护,程序结构清晰,关键是松散耦合

    工厂呢,就是

    例如,如果我要个对象,就会让工厂去创建,创建完成,给你返回个结果。

    假如你去吃麦当劳,你说要个汉堡,你不会自己去做吧,相当于,你跟服务员说,我要个汉堡,服务员跟后面的“工厂”说,然后工厂帮你做个汉堡,然后“工厂”会给你个结果

    三层架构,数据层(DAL)、逻辑层(BLL)、表示层(UI);
    从功能上来说:
    表示层就象你去饭店吃饭,你点了一个清真鲈鱼。
    业务层负责洗、切、蒸等。
    数据层负责提供鱼、油、盐等。


    确切的说现在应用一般为7层结构

    ---DBUtility数据层基类
    ---DALFactory数据层工厂类
    ---IDAL接口层
    ---SQLDAL接口实现层
    ---Model实体类
    ---Logic业务逻辑层
    ---Web表示层

     

  • 相关阅读:
    我的那些年(11)~去一家创业公司做架构师
    springboot~hazelcast缓存中间件
    我的那些年(10)~来到更大的团队,做了架构师
    springboot~maven制作底层公用库
    Vesions ignore & ld: library not found for -l...
    iOS利用单例实现不同界面间的数据传输
    UVA 10006
    VS2010打开就自动关闭问题解决
    模板方法模式(Template Method)
    HDU 4279
  • 原文地址:https://www.cnblogs.com/lhws/p/1826818.html
Copyright © 2020-2023  润新知