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类型。