0

0

详解C# .NET更智能的数据库操作的封装

迷茫

迷茫

发布时间:2017-03-26 14:36:01

|

1819人浏览过

|

来源于php中文网

原创

前述:

  对数据库操作的封装,相信网络上已经有一大堆,ORM框架,或者是.NET本身的EF,都很好的支持数据库操作。这篇文章是分享自己所思考的,对数据库操作的简单封装。我对于这篇文章,认为被浏览者所关注重点的是怎么分析设计数据库操作封装,代码是其次。而且,这是我第一篇文章,为了想好怎么实现花了些天,代码是博客发表时现写的。所以我想,使用可能还有bug,而且没有try catch异常的设计。

  这个框架我理应做到对数据库无关,无论是哪个数据库都能够使用。不过,重点在于分析,而不是代码。所以,为了更好的阐述,我只做了对sql Server的封装,对其他的话,浏览者可以自己设计;框架可支持链式写法,我想,在许多编程语言,大家对链式写法大不会陌生,所以我想,数据库访问也可以做成链式的模式。这个框架不需要写sql语句,对任何的操作,都只需要简单的传所需的参数,封装好对应的操作。

  在阅读文章之前最好有些泛型、反射、Link的基础,不然阅读可能会有些费劲。

 

进入重点:

  框架的结构比较简单,使用简单工厂模式,因此笔者就不画一张UML图来解释,而用文字对里面方法进行描述。

  在设计工厂接口时候,应该考虑接口中应该含有链式写法必须的三个阶段(也称部分):数据库基本操作(打开,关闭,创建等)、数据库的增删改查、数据库返回的数据(这里我做为执行阶段,估计大家会好奇为什么不是上一阶段,大家往下阅读就知道)和不是必须的事务操作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace Dal
{
    public interface DbHelper
    {
        /// 
        /// 创建数据库连接
        /// 
        /// 连接字符串
        /// 
        DbHelper createConnection(string connectionString);

        /// 
        /// 打开数据库
        /// 
        /// 
        DbHelper openConnection();

        /// 
        /// 关闭数据库
        /// 
        /// 
        DbHelper closeConnection();

        /// 
        /// 释放sqlConnection对象
        /// 
        void DisposedConnection();

        /// 
        /// 释放sqlCommand对象
        /// 
        void DisposedCommand();

        /// 
        /// 创建sqlCommand对象
        /// 
        /// 
        DbHelper createCommand();

        /// 
        /// 设置sqlCommand的类型
        /// 
        /// CommandType枚举类型
        /// 
        DbHelper setCommandType(CommandType type);
        
        /// 
        /// 要查询的表(多表以逗号隔开)、存储过程、视图名
        /// 
        /// 
        /// 
        DbHelper FromName(string Name);

        /// 
        /// 创建事务
        /// 
        /// 
        DbHelper beginTransaction();

        /// 
        /// 事务回滚
        /// 
        /// 
        DbHelper TransactionRowBack();

        /// 
        /// 事务提交
        /// 
        /// 
        DbHelper TransactionCommit();

        /// 
        /// 对多张表间的列进行联系
        /// 
        /// 表间联系的字段
        /// 
        DbHelper ForMulTable(string Fields);

        /// 
        /// 查询
        /// 
        /// 查询字段
        /// 查询条件字典
        /// 其他条件
        /// 
        DbHelper Select(string Fields = "*", Dictionary Where = null, string otherWhere = "");

        /// 
        /// 更新
        /// 
        /// 需要更新的对象
        /// 更新条件
        /// 更新字段
        /// 其他条件
        /// 
        DbHelper Update(object model, Dictionary Where, string Fields = "", string otherWhere = "");

        /// 
        /// 插入
        /// 
        /// 需要插入的对象
        /// 需要插入的字段
        /// 
        DbHelper Insert(object model, string Fields = "");

        /// 
        /// 删除
        /// 
        /// 删除条件
        /// 其他条件
        /// 
        DbHelper Delete(Dictionary Where, string otherWhere = "");


        /// 
        /// 查询返回List
        /// 
        /// 模型
        /// 
        List ToList()
            where T : class ,new();

        
        /// 
        /// 查询返回DataSet
        /// 
        /// 
        /// 
        DataSet ToDataSet(string DatasetName);

        /// 
        /// 查询返回DataTable
        /// 
        /// 
        DataTable ToDataTable();

        /// 
        /// 执行存储过程
        /// 
        /// 存储过程参数
        /// 
        DbHelper ExcuteProc(Dictionary Parameter);

        /// 
        /// 执行返回查询第一行第一列值
        /// 
        /// 
        object Result();

        /// 
        /// 返回执行的影响行数
        /// 
        /// 
        int ExcuteResult();

        /// 
        /// 用户自定义sqlCommand
        /// 
        /// 委托
        void UserDefineOperation(Action fun);
    }
}

  好了,看完代码,大家对具体实现应该还是一头雾水,那,接下来一步步分析具体实现,是以sql Server来分析。

  在具体实现的类中SQLHelper,设计中所必须的字段。在一开始设计时候,我在想怎么给各个数据库兼容,因为它们使用的执行对象Command是不同的,所以为了能够更好封装的库,将其设计sqlCommand不暴露给外部使用,而是在内部使用。暴露方法能够设置com的属性,以及ExcuteName就存放着执行数据的对象。

//连接字符串
        string ConnectionString;
        
        //数据库连接对象
        private SqlConnection conn;

        //执行对象
        SqlCommand com;

        //表、存储过程、视图名称
        string ExcuteName;

        //事务
        SqlTransaction tran;

        //sql语句
        StringBuilder sqlBuilderString;

        //参数
        SqlParameter[] paras;

 第一部分:数据库基本操作

  createConnection方法:这个方法其实就是new sqlConnection,对其赋值connectionString,也采用了大家一般使用的单例模式,这样也会在执行的时候比较安全。不过这个单例是指一个Helper对应一个sqlConnection,而不是设计为static,因为我觉得有些项目在访问的数据库有可能有多个。而且在创建时候,对其进行打开和关闭一次,为了检查能否真的能使用。

public DbHelper createConnection(string connectionString)
        {
            if (!ConnectionCanUse())
            {
                this.ConnectionString = connectionString;
                conn = new SqlConnection(this.ConnectionString);
            }

            return this;
        }

        /// 
        /// 检查conn是否能用
        /// 
        /// 
        public bool ConnectionCanUse()
        {
            if (conn == null)
                return false;
            try
            {
                conn.Open();
                conn.Close();
            }catch(Exception e)
            {
                return false;
            }
            
            return true;
        }

  打开、关闭、释放connection和创建command就不作解释了,因为里面就一句话。

  关于基本操作,还有就是关于sqlCommandType的设置,因为存储过程和普通的语句等操作字符串明显是不同,因此要写个方法来设置它。

  第二部分:增删改查的操作 这里就解释为什么sql语句不是在这个阶段执行。我觉得,如果将具体的执行放在这个阶段,那么就会导致方法重载过多,为什么?因为并不是所有人都能考虑到使用者要返回的类型,比如我想要List,或者DataSet等等,而且还会将这个方法的作用过重:在我设计的这些方法中,实操作的是对sql语句的生成,所以说为什么不能在这边执行,那么就不能重用。是吧,这样设计很灵活,将数据库真正执行放在下个阶段。而且这些方法都是链式的写法,所以会对执行能够很灵活的控制,最重要能够重用,不需要写别的重载方法,只需要一个方法。

  生成sql语句在这也是简单的封装,如果要做起真的框架,我觉得sql字符串的组合还应该创建一个类,来更智能的组合用户的需求。

95Shop仿醉品商城
95Shop仿醉品商城

95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we

下载

  自然,里面使用到反射、Linq。不过笔者也一步步解释,将怎么设计分享给大家。

  大家看到Select、Insert、Update、Delete的接口都有Where的条件字典。没错,反射就在这里使用。为了考虑到数据库的安全,所以sql自然只是简单的拼接,还应该使用参数。所以,反射就用在Where生成参数上。大家也许还看到别的otherWhere,这个怎么不设计成参数,因为Where能够实现的,其实就是赋值语句,也就是表内某字段 = 值,所以需要。在otherWhere中,存放的是其他特殊的条件。前面说这里设计的不完美,就因为如此,其实有些条件 like 或者 使用or ,虽然能够写在otherWhere中,但是没办法使用参数来控制。

  那么接下来就是Fiels参数了,这个在各个方法充当不同的作用。Select是查询的字段,Update中是更新的字段,在Insert中是插入的字段,这样就灵活的控制了。在这些字段为空的时候,默认为全部,反射在这里就使用了,遍历模型对象中的属性,然后将它们一个个填进sql语句中。在这里比较注意的应该是插入,因为大家在写sql语句时候是这样的 insert tableName values(value,value....)这样的格式,这样是因为sql会自己对应值插入,而在程序中的模型类中,我想大家写属性可不是按顺序的吧,所以在反射遍历时候,就有可能将几个本来待在某个列位置的值去换了位置的情况。所以,这里在遍历的时候,应该按插入的完全格式来设计,也就是 insert tableName(Field,Field...) values(value,value...)。

  在这几个方法中,Delete最简单。

public DbHelper Select(string Fields = "*",Dictionary Where = null,string otherWhere = "")
        {
            sqlBuilderString = new StringBuilder();

            sqlBuilderString.AppendLine("select " + Fields + " from " + this.ExcuteName);
            List paras = new List();
            sqlBuilderString.AppendLine(" where 1 = 1 ");            
            if (Where != null && Where.Count > 0)
            {
                paras = new List();                //遍历Where,将里面的条件添加到sqlParamter和sql语句中
                Where.Keys.ToList().ForEach(o => {
                    sqlBuilderString.AppendLine(" and "+ o + " = @" + o);
                    paras.Add(new SqlParameter(o, Where[o]));
                });
            }            if(!string.IsNullOrEmpty(otherWhere))
            {
                sqlBuilderString.AppendLine(otherWhere);
            }            this.paras = paras.ToArray();            return this;
        }
public DbHelper Update(object model,Dictionary Where,string Fields = "", string otherWhere = "")
        {
            Type t = model.GetType();
            List keys = Where.Keys.ToList();
            sqlBuilderString = new StringBuilder();            bool firstnode = true;
            sqlBuilderString.AppendLine("update "+ExcuteName + " set ");
            List paras = new List();            if(string.IsNullOrEmpty(Fields))
            {
                t.GetProperties().ToList().ForEach(o =>
                {                    if (!firstnode)
                        sqlBuilderString.Append(",");                    else
                        firstnode = false;                    if(!keys.Contains(o.Name))
                    {
                        sqlBuilderString.AppendLine(o.Name + " = @"+o.Name);
                        paras.Add(new SqlParameter(o.Name,o.GetValue(model,null)));
                    }
                });
            }else
            {
                Fields.Split(',').ToList().ForEach(o =>
                {
                    sqlBuilderString.AppendLine(o + " = @" + o);
                    paras.Add(new SqlParameter(o, t.GetProperty(o).GetValue(model, null)));
                });
            }            this.paras = paras.ToArray();            return this;
        }
public DbHelper Insert(object model,string Fields = "")
        {
            List paras = new List();
            Type t = model.GetType();
            sqlBuilderString = new StringBuilder();
            sqlBuilderString.AppendLine("insert " + ExcuteName);            if(string.IsNullOrEmpty(Fields))
            {                string s = "";                string s1="";
                t.GetProperties().ToList().ForEach(o =>
                {
                    s += o.Name + ",";
                    s1 += " @" + o.Name + ",";
                    paras.Add(new SqlParameter(o.Name, o.GetValue(model, null)));
                });
                s.Remove(s.LastIndexOf(','),1);
                s1.Remove(s.LastIndexOf(','), 1);
                sqlBuilderString.AppendLine("(" + s + ")");
                sqlBuilderString.AppendLine(" values(" + s1 + ")");
            }else
            {
                sqlBuilderString.AppendLine("(" + Fields + ")");                string s = "";
                Fields.Split(',').ToList().ForEach(o =>
                {
                    s += " @" + o + ",";
                    paras.Add(new SqlParameter(o, t.GetProperty(o).GetValue(model, null)));
                });
                sqlBuilderString.AppendLine(" values(" + s + ")");
            }            this.paras = paras.ToArray();            return this;
        }
public DbHelper Delete(Dictionary Where,string otherWhere = "")
        {
            sqlBuilderString = new StringBuilder();
            List paras = new List();
            sqlBuilderString.AppendLine("delete " + ExcuteName);
            sqlBuilderString.AppendLine(" where 1 = 1 ");

            Where.Keys.ToList().ForEach(o =>
            {
                sqlBuilderString.AppendLine(" and " + o + " = @" + o);
                paras.Add(new SqlParameter(o, Where[o]));
            });            this.paras = paras.ToArray();            return this;
        }

最后一个阶段,那就是执行阶段,这里封装了些执行的方法。

这个也是简单,最重要的方法应该是setCommand,这个方法是对sqlCommand进行设置,执行的语句,以及添加参数。

private void setCommand()
        {            if(com.CommandType== CommandType.StoredProcedure)
            {                this.com.CommandText = ExcuteName;
            }else
            {                this.com.CommandText = sqlBuilderString.ToString();
            }            this.paras.ToList().ForEach(o =>
            {                this.com.Parameters.Add(o);
            });
        }

其他就是执行的语句。

public List ToList()            where T:class ,new()
        {
            List list = new List();
            setCommand();
            SqlDataReader reader = com.ExecuteReader();
            Type t = typeof(T);
            List pros = t.GetProperties().ToList();            while(reader.Read())
            {
                T model = new T();
                pros.ForEach(o =>
                {
                    o.SetValue(model, reader[o.Name], null);
                });
                list.Add(model);
            }
            reader.Dispose();            return list;
        }        public DataSet ToDataSet(string DatasetName = "")
        {
            DataSet ds = new DataSet();
            setCommand();
            SqlDataAdapter adapter = new SqlDataAdapter(com);

            adapter.Fill(ds, string.IsNullOrEmpty(DatasetName) ? this.ExcuteName.Replace(",", "_") : DatasetName);
            adapter.Dispose();            return ds;
        }        public DataTable ToDataTable()
        {
            DataTable dt = new DataTable();
            setCommand();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            adapter.Fill(dt);
            adapter.Dispose();            return dt;
        }        public object Result()
        {
            setCommand();            return com.ExecuteScalar();
        }        public int ExcuteResult()
        {
            setCommand();            return com.ExecuteNonQuery();
        }        public DbHelper ExcuteProc(Dictionary Parameter)
        {
            List paras = new List();

            Parameter.Keys.ToList().ForEach(o =>
            {
                paras.Add(new SqlParameter(o, Parameter[o]));
            });            return this;
        }

当然,还不能少了让用户自定义的方法,所以最后还留了个方法,参数是委托。委托里面的参数还是动态类型,这就懂了吧,想用户怎么用,你就怎么定义。

public void UserDefineOperation(Action fun)
        {
            fun(this.com);
        }

好了,设计也就到这里,下面就贴上SQLHelper完整的代码。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;using System.Data.SqlClient;using System.Reflection;namespace Dal
{    public class SQLHelper:DbHelper
    {        //连接字符串
        string ConnectionString;        
        //数据库连接对象
        private SqlConnection conn;        //执行对象        SqlCommand com;        //表、存储过程、视图名称
        string ExcuteName;        //事务        SqlTransaction tran;        //sql语句        StringBuilder sqlBuilderString;        //参数        SqlParameter[] paras;        private SQLHelper()
        {

        }        /// 
        /// 创建sqlHelper静态方法        /// 
        /// 
        public static DbHelper getInstance()
        {            return new SQLHelper();
        }        /// 
        /// 
        /// 
        /// 
        /// 
        public DbHelper createConnection(string connectionString)
        {            if (!ConnectionCanUse())
            {                this.ConnectionString = connectionString;
                conn = new SqlConnection(this.ConnectionString);
            }            return this;
        }        /// 
        /// 检查conn是否能用        /// 
        /// 
        public bool ConnectionCanUse()
        {            if (conn == null)                return false;            try
            {
                conn.Open();
                conn.Close();
            }catch(Exception e)
            {                return false;
            }            
            return true;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper openConnection()
        {            if(conn.State != ConnectionState.Open)            this.conn.Open();            return this;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper closeConnection()
        {            if(conn.State != ConnectionState.Closed)            this.conn.Close();            return this;
        }        /// 
        /// 
        /// 
        public void DisposedConnection()
        {            if (!ConnectionBeUsed())                this.conn.Dispose();
        }        /// 
        /// 检查数据库是否在被打开使用        /// 
        /// 
        public bool ConnectionBeUsed()
        {            if(conn.State == ConnectionState.Open)                return true;            return false;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper createCommand()
        {            if (this.com == null)
            {                this.com = new SqlCommand();
                com.Connection = this.conn;
            }           
            return this;
        }        /// 
        /// 
        /// 
        public void DisposedCommand()
        {            this.com.Dispose();
        }        /// 
        /// 
        /// 
        /// 
        /// 
        public DbHelper setCommandType(CommandType type)
        {            this.com.CommandType = type;            return this;
        }        /// 
        /// 
        /// 
        /// 
        /// 
        public DbHelper FromName(string Name)
        {            this.ExcuteName = Name;            return this;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper beginTransaction()
        {            this.tran = conn.BeginTransaction();
            com.Transaction = this.tran;            return this;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper TransactionRowBack()
        {            if(tran!=null)
            {
                tran.Rollback();
            }            return this;
        }        /// 
        /// 
        /// 
        /// 
        public DbHelper TransactionCommit()
        {            if(tran!=null)
            {
                tran.Commit();
                tran = null;
            }            return this;
        }        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public DbHelper Select(string Fields = "*",Dictionary Where = null,string otherWhere = "")
        {
            sqlBuilderString = new StringBuilder();

            sqlBuilderString.AppendLine("select " + Fields + " from " + this.ExcuteName);
            List paras = new List();
            sqlBuilderString.AppendLine(" where 1 = 1 ");            
            if (Where != null && Where.Count > 0)
            {
                paras = new List();                //遍历Where,将里面的条件添加到sqlParamter和sql语句中
                Where.Keys.ToList().ForEach(o => {
                    sqlBuilderString.AppendLine(" and "+ o + " = @" + o);
                    paras.Add(new SqlParameter(o, Where[o]));
                });
            }            if(!string.IsNullOrEmpty(otherWhere))
            {
                sqlBuilderString.AppendLine(otherWhere);
            }            this.paras = paras.ToArray();            return this;
        }        
        public DbHelper ForMulTable(string Fields)
        {
            List tables = ExcuteName.Split(',').ToList();
            Fields.Split(',').ToList().ForEach(o =>
            {                for(int i = 0;i Where,string Fields = "", string otherWhere = "")
        {
            Type t = model.GetType();
            List keys = Where.Keys.ToList();
            sqlBuilderString = new StringBuilder();            bool firstnode = true;
            sqlBuilderString.AppendLine("update "+ExcuteName + " set ");
            List paras = new List();            if(string.IsNullOrEmpty(Fields))
            {
                t.GetProperties().ToList().ForEach(o =>
                {                    if (!firstnode)
                        sqlBuilderString.Append(",");                    else
                        firstnode = false;                    if(!keys.Contains(o.Name))
                    {
                        sqlBuilderString.AppendLine(o.Name + " = @"+o.Name);
                        paras.Add(new SqlParameter(o.Name,o.GetValue(model,null)));
                    }
                });
            }else
            {
                Fields.Split(',').ToList().ForEach(o =>
                {
                    sqlBuilderString.AppendLine(o + " = @" + o);
                    paras.Add(new SqlParameter(o, t.GetProperty(o).GetValue(model, null)));
                });
            }            this.paras = paras.ToArray();            return this;
        }        public DbHelper Insert(object model,string Fields = "")
        {
            List paras = new List();
            Type t = model.GetType();
            sqlBuilderString = new StringBuilder();
            sqlBuilderString.AppendLine("insert " + ExcuteName);            if(string.IsNullOrEmpty(Fields))
            {                string s = "";                string s1="";
                t.GetProperties().ToList().ForEach(o =>
                {
                    s += o.Name + ",";
                    s1 += " @" + o.Name + ",";
                    paras.Add(new SqlParameter(o.Name, o.GetValue(model, null)));
                });
                s.Remove(s.LastIndexOf(','),1);
                s1.Remove(s.LastIndexOf(','), 1);
                sqlBuilderString.AppendLine("(" + s + ")");
                sqlBuilderString.AppendLine(" values(" + s1 + ")");
            }else
            {
                sqlBuilderString.AppendLine("(" + Fields + ")");                string s = "";
                Fields.Split(',').ToList().ForEach(o =>
                {
                    s += " @" + o + ",";
                    paras.Add(new SqlParameter(o, t.GetProperty(o).GetValue(model, null)));
                });
                sqlBuilderString.AppendLine(" values(" + s + ")");
            }            this.paras = paras.ToArray();            return this;
        }        public DbHelper Delete(Dictionary Where,string otherWhere = "")
        {
            sqlBuilderString = new StringBuilder();
            List paras = new List();
            sqlBuilderString.AppendLine("delete " + ExcuteName);
            sqlBuilderString.AppendLine(" where 1 = 1 ");

            Where.Keys.ToList().ForEach(o =>
            {
                sqlBuilderString.AppendLine(" and " + o + " = @" + o);
                paras.Add(new SqlParameter(o, Where[o]));
            });            this.paras = paras.ToArray();            return this;
        }        private void setCommand()
        {            if(com.CommandType== CommandType.StoredProcedure)
            {                this.com.CommandText = ExcuteName;
            }else
            {                this.com.CommandText = sqlBuilderString.ToString();
            }            this.paras.ToList().ForEach(o =>
            {                this.com.Parameters.Add(o);
            });
        }        public List ToList()            where T:class ,new()
        {
            List list = new List();
            setCommand();
            SqlDataReader reader = com.ExecuteReader();
            Type t = typeof(T);
            List pros = t.GetProperties().ToList();            while(reader.Read())
            {
                T model = new T();
                pros.ForEach(o =>
                {
                    o.SetValue(model, reader[o.Name], null);
                });
                list.Add(model);
            }
            reader.Dispose();            return list;
        }        public DataSet ToDataSet(string DatasetName = "")
        {
            DataSet ds = new DataSet();
            setCommand();
            SqlDataAdapter adapter = new SqlDataAdapter(com);

            adapter.Fill(ds, string.IsNullOrEmpty(DatasetName) ? this.ExcuteName.Replace(",", "_") : DatasetName);
            adapter.Dispose();            return ds;
        }        public DataTable ToDataTable()
        {
            DataTable dt = new DataTable();
            setCommand();
            SqlDataAdapter adapter = new SqlDataAdapter(com);
            adapter.Fill(dt);
            adapter.Dispose();            return dt;
        }        public object Result()
        {
            setCommand();            return com.ExecuteScalar();
        }        public int ExcuteResult()
        {
            setCommand();            return com.ExecuteNonQuery();
        }        public DbHelper ExcuteProc(Dictionary Parameter)
        {
            List paras = new List();

            Parameter.Keys.ToList().ForEach(o =>
            {
                paras.Add(new SqlParameter(o, Parameter[o]));
            });            return this;
        }        public void UserDefineOperation(Action fun)
        {
            fun(this.com);
        }
    }
}

最后还有两个事务的方法,前面忘记说了,其实就是SqlTransaction,在里面的sqlCommand加上这个,就可以实现。或许有人会问,如果有同一时间段有好几个sqlCommand怎么办?不会的,sqlCommand我也设置成单例,就不会发生控制不了的事情了。

 

  结束语:第一次的博客,我虽然做过不少“幼稚作品”,毕竟我是大三学生,如果随意的写文章,我担心只是会成为被嘲笑的对象,幼稚的“作品”也不好意思放在网上给大家看。所以,在想了几天,写了我觉得蛮有用的封装,虽然可能对许多项目不起作用,但是读者可以自己在更深的思考。

  这个框架,我觉得应该还能更好的封装,比如从sql语句组合,调用的时候发生异常处理,怎么更好的实现链式组合,多数据库的处理控制,加上锁我觉得也是可以,毕竟做web的时候可不是像winform,每个端都有自己的connection。还有一个我觉得不错的,就是在模型上做处理,加上特性,让框架能够识别主键,外键,在程序中建立sql中的联系等。那么就给读者思考了。

 

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 6.8万人学习

C 教程
C 教程

共75课时 | 4万人学习

C++教程
C++教程

共115课时 | 12.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号