通过反射,将datatable转换为List集合(反射读取实体类的属性,并赋值),通过接口来实现MySql和MsSql数据的切换(二层反射),静态构造函数,抽象类和接口的区别
1: BLL层的 DataProvider.cs 这个类,是一个抽象类,用来描述各种各样的DAL层的方法(但是没有方法的实现),他是DAL层的 MySqlDataProvider.cs的基类
同时,他还根据 web.config 里面设置的 数据库的类型,来反射是 MySql的数据库操作,还是MsSql的数据库的操作
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Configuration; using Model; namespace BLL { public abstract class DataProvider //这个抽象类,相当于是父类 { private static DataProvider objProvider = null; //读取需要反射的类型, 是mysql还是mssql private static string DataBaseType = ConfigurationManager.AppSettings["DataBaseType"]; //静态构造函数,在类初始化的时候执行,不用加 public / private 没有意义,因为这个.net自动来调用 //在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类 static DataProvider() { Type type = Type.GetType(DataBaseType, true); objProvider = (DataProvider)Activator.CreateInstance(type);//反射一个数据库操作类的实例,并用父类来指向 } public static DataProvider Instance() { return objProvider; } #region 用户添加的各种 抽象方法 //获得所有的人,返回一个datatable public abstract DataTable GetAllPerson(); //添加一个人 public abstract bool AddUser(Model.Person p); //获得所有的人,这里用的是用T来表示 泛型约束 public abstract List<T> GetList<T>(DataTable dt); #endregion } }
web.config
<appSettings> <add key="DataBaseType" value="DAL.MySqlDataProvider,DAL"/> </appSettings> <connectionStrings> <add name="connStr" connectionString="database=fanshetest;Password=123456;uid=root;server=localhost;Port=3306;" /> </connectionStrings>
2: DAL层的 MySqlProvider.cs ,继承 BLL层的 DataProvider.cs ,实现里面的各个读取数据库增删改查的方法。同时,也有反射在里面,用于根据 Model层来反射出Model层的各个属性,把数据表每一行的每一个字段的值,赋值给每个Model的属性
using System; using System.Collections.Generic; using System.Text; using System.Data; //datatable之类 using MySql.Data.MySqlClient; //mysql using Model; //实体 using System.Reflection; //反射 using BLL; namespace DAL { public class MySqlDataProvider :BLL.DataProvider { //mysql数据库的助手类 MySqlHelper helper = null; public MySqlDataProvider() { helper = new MySqlHelper(); } //获得所有的人,返回一个datatable public override DataTable GetAllPerson() { DataTable dt = new DataTable(); MySqlDataReader dr = helper.ExecuteReader(System.Data.CommandType.Text, "select * from person"); dt.Load(dr); return dt; } //添加一个人 public override bool AddUser(Model.Person p) { MySqlParameter[] para = new MySqlParameter[]{ new MySqlParameter("@UserName",MySqlDbType.VarChar,200), new MySqlParameter("@AddTime",MySqlDbType.DateTime), new MySqlParameter("@Address",MySqlDbType.VarChar,200) }; para[0].Value = p.UserName; para[1].Value = p.AddTime; para[2].Value = p.Address; int res = helper.ExecuteNonQuery(CommandType.Text, "INSERT INTO person(UserName,AddTime,Address) VALUES(@UserName,@AddTime,@Address)", para); return res > 0 ? true : false; } //获得所有的人,这里用的是用T来表示 泛型约束 public override List<T> GetList<T>(DataTable dt) { List<T> list = new List<T>(); if (dt == null || dt.Rows.Count < 1) return list; //default(int) 则是0 default(Person)表示person的默认值,也就是null。 //default(T)的值是null,也就是说 T t出来的值是null,可否直接相当于是 T t出来一个Model.Person呢? //可以,Activator.CreateInstance<T>()实例出来的就是Model.Person //那么下面获得所有属性可以用 t.GetType().GetProperties() T t = default(T); System.Reflection.PropertyInfo[] pro = typeof(T).GetProperties();//t不为null的时候可以用t.GetType().GetProperties() foreach (DataRow row in dt.Rows) //循环每一行的值 { t = Activator.CreateInstance<T>(); //每次循环,必须重新弄一个出来 foreach (PropertyInfo item in pro) //循环每一列,进行绑定 { string tempname = item.Name; object value = row[tempname]; //数据库里面的值不能为null,或者说不能为System.DBNull item.SetValue(t, value, null);//这里是用的属性来绑定值 属性.SetValue(你要绑定的对象,属性值,索引) } list.Add(t); } return list; } } }
3: DAL层的 MySqlHelper.cs 这个是 Mysql数据库的数据库操作助手类,用于编写 最底层的代码,实际就是最底层的 ExecuteNonQuery,ExecuteScalar,ExecuteReader
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Configuration;//不仅仅在这里学using,还要在项目中右键引用 using MySql.Data.MySqlClient;// MySql namespace DAL { /// <summary>基于MySQL的数据层基类 /// /// </summary> public class MySqlHelper { #region 数据库连接字符串 public readonly static string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ToString(); #endregion #region PrepareCommand -> Command预处理 /// <summary> /// Command预处理 /// </summary> /// <param name="conn">MySqlConnection对象</param> /// <param name="trans">MySqlTransaction对象,可为null</param> /// <param name="cmd">MySqlCommand对象</param> /// <param name="cmdType">CommandType,存储过程或命令行</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组,可为null</param> private void PrepareCommand(MySqlConnection conn, MySqlTransaction trans, MySqlCommand cmd, CommandType cmdType, string cmdText, MySqlParameter[] 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 (MySqlParameter parm in cmdParms) cmd.Parameters.Add(parm); } } #endregion #region ExecuteNonQuery ->执行命令 /// <summary> /// 执行命令 /// </summary> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns>返回受引响的记录行数</returns> public int ExecuteNonQuery( CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection conn = new MySqlConnection(connectionString)) { PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } } /// <summary> /// 执行命令 /// </summary> /// <param name="conn">Connection对象</param> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns>返回受引响的记录行数</returns> public int ExecuteNonQuery(MySqlConnection conn, CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } /// <summary> /// 执行事务 /// </summary> /// <param name="trans">MySqlTransaction对象</param> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns>返回受引响的记录行数</returns> public int ExecuteNonQuery(MySqlTransaction trans, CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(trans.Connection, trans, cmd, cmdType, cmdText, cmdParms); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } #endregion #region ExecuteScalar ->执行命令,返回第一行第一列的值 /// <summary> /// 执行命令,返回第一行第一列的值 /// </summary> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns>返回Object对象</returns> public object ExecuteScalar( CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection connection = new MySqlConnection(connectionString)) { PrepareCommand(connection, null, cmd, cmdType, cmdText, cmdParms); object val = cmd.ExecuteScalar(); cmd.Parameters.Clear(); return val; } } /// <summary> /// 执行命令,返回第一行第一列的值 /// </summary> /// <param name="connectionString">数据库连接字符串</param> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns>返回Object对象</returns> public object ExecuteScalar(MySqlConnection conn, CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); object val = cmd.ExecuteScalar(); cmd.Parameters.Clear(); return val; } #endregion #region ExecuteReader ->执行命令或存储过程,返回MySqlDataReader对象 /// <summary> /// 执行命令或存储过程,返回MySqlDataReader对象 /// 注意MySqlDataReader对象使用完后必须Close以释放MySqlConnection资源 /// </summary> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组</param> /// <returns></returns> public MySqlDataReader ExecuteReader( CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); MySqlConnection conn = new MySqlConnection(connectionString); try { PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); MySqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); cmd.Parameters.Clear(); return dr; } catch { conn.Close(); throw; } } #endregion #region ExecuteDataSet ->执行命令或存储过程,返回DataSet对象 /// <summary> /// 执行命令或存储过程,返回DataSet对象 /// </summary> /// <param name="cmdType">命令类型(存储过程或SQL语句)</param> /// <param name="cmdText">SQL语句或存储过程名</param> /// <param name="cmdParms">MySqlCommand参数数组(可为null值)</param> /// <returns></returns> public DataSet ExecuteDataSet( CommandType cmdType, string cmdText, params MySqlParameter[] cmdParms) { MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection conn = new MySqlConnection(connectionString)) { PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); MySqlDataAdapter da = new MySqlDataAdapter(cmd); DataSet ds = new DataSet(); da.Fill(ds); conn.Close(); cmd.Parameters.Clear(); return ds; } } #endregion } }
4:Model层的 Person 类,对应数据库里面的数据结构
using System;
using System.Collections.Generic;
using System.Text;
namespace Model
{
public class Person
{
public int Id { get; set; }
public string UserName { get; set; }
public DateTime AddTime { get; set; }
public string Address { get; set; }
}
}
5:前台页面调用方式
using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using BLL; using Model; namespace FanSheWeb { public partial class _Default : System.Web.UI.Page { DataProvider dp = DataProvider.Instance(); protected void Page_Load(object sender, EventArgs e) { gvResult.DataSource = dp.GetList<Person>(dp.GetAllPerson()); gvResult.DataBind(); } protected void btnAdd_Click(object sender, EventArgs e) { string user = txtUser.Text.Trim(); string address = txtAddress.Text.Trim(); dp.AddUser(new Model.Person() { UserName = user, Address = address, AddTime = DateTime.Now }); Response.Redirect(Request.RawUrl); } } }
在使用静态构造函数的时候应该注意以下几点:
1、静态构造函数既没有访问修饰符,也没有参数。
--因为是.NET调用的,所以像public和private等修饰符就没有意义了。
2、在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类。
--也就是说我们无法直接调用静态构造函数,也不可能知道静态构造函数何时会被调用。
3、一个类只能有一个静态构造函数。
4、无参数的构造函数可以与静态构造函数共存。
--尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突。
5、最多只运行一次。
6、静态构造函数不可以被继承。
7、如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。
一个类可以有多个接口 只能有继承一个父类
抽象类可以有构造方法,接口中不能有构造方法。
抽象类中可以有普通成员变量,接口中没有普通成员变量.
接口里边全部方法都必须是abstract的 抽象类的可以有实现了的方法
抽象类中的抽象方法的访问类型可以是public,protected 但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型
抽象类中可以包含静态方法,接口中不能包含静态方法
抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。