摘要:最近有病呆在家里,不是次就是睡,不只日夜颠倒了,还胖了不少。不过空余的时间总不能浪费掉,所以开始了一个新的跨数据库访问组件。不过那个组件要写比较长时间了,所以一时不会做得完。不过今天用其中的技术做了个有用的例子,发到这里给大家参考一下。这个例子的大概意思是,程序员参考存储的定义,写出一个接口出来,并且不需要写具体的实现代码,就能调用该接口了!也就是说,程序员不需要写以下类似的代码了:
SqlCommand cmd=new SqlCommand("UpdateTopic",conn);cmd.CommandType=CommandType.StoredProcedure;SqlParameter pTitle=new SqlParameter("@title",SqlDbType.NVarChar,80);pTitle.Value=title;cmd.Parameters.Add(pTitle);//.
程序的例子如下
/**//****************************************************************\ * * 用 System.Reflection.Emit 来自动生成调用储存过程的实现! * * By http://lostinet.com * * Copyrights : Not-Reversed * \****************************************************************///使用的例子namespace Lostinet.Sample{ using System; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; //定义一个接口,用于定义存储过程 interface INorthwindStoredProcedures { //定义存储过程对应的方法 DataSet CustOrderHist(string CustomerID); //如果储存过程名字和方法名字不同,应该用SqlAccessAttribute来进行说明 [SqlAccess("Employee Sales By Country")] DataTable EmployeeSalesByCountry(DateTime Beginning_Date,DateTime Ending_Date); //more //MORE Ideas.. //直接执行SQL语句? //[SqlAccess(SqlAccessType.SqlQuery,"SELECT * FROM Employees WHERE EmployeeID=@EmpId")] //DataTable SelectEmployee(int EmpId); } class ConsoleApplication { [STAThread] static void Main(string[] args) { using(SqlConnection conn=new SqlConnection("server=(local);trusted_connection=true;database=northwind")) { //一句话就把实现创建了! //需要传如 SqlConnection 和 SqlTransaction //SqlTransaction可以为null //这个好就好在,只要能得到SqlConnection/SqlTransaction就能用这个方法了,所以兼容 Lostinet.Data.SqlScope INorthwindStoredProcedures nsp=(INorthwindStoredProcedures) StoredProcedure.CreateStoredProcedureInterface(typeof(INorthwindStoredProcedures),conn,null); //调用储存过程并且显示 ShowData("CustOrderHist ALFKI",nsp.CustOrderHist("ALFKI")); ShowData("Employee Sales By Country",nsp.EmployeeSalesByCountry(new DateTime(1998,1,1),new DateTime(1999,1,1))); } } static void ShowData(string title,object data) { Form f=new Form(); f.Width=600; f.Height=480; f.Text=title; DataGrid grid=new DataGrid(); grid.Dock=DockStyle.Fill; grid.DataSource=data; f.Controls.Add(grid); f.ShowDialog(); } }}//实现方法(不完整)#region //实现方法(不完整)namespace Lostinet.Sample{ using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; using System.Data; using System.Data.SqlClient; //这个类作为实现的基类, //目的是提供储存 SqlConnection/SqlTransaction 和公用的一些方法 //这个类必须为public,否则无法继承 //但开发者不会显式访问这个类 public class SPInterfaceBase : IDisposable { public SPInterfaceBase() { } public void Dispose() { } //CreateStoredProcedureInterface会把相关的值SqlConnection/SqlTransaction存到这里 public SqlConnection connection; public SqlTransaction transaction; //创建一个SqlCommand public SqlCommand CreateCommand(string spname) { SqlCommand cmd=new SqlCommand(spname,connection,transaction); cmd.CommandType=CommandType.StoredProcedure; //TODO: //cmd.Parameters.Add("@ReturnValue", return cmd; } //由 Type 推算出 SqlDbType , 未完成 SqlDbType GetSqlDbType(Type type) { //TODO:switch(type) return SqlDbType.NVarChar; } //定义参数 public void DefineParameter(SqlCommand cmd,string name,Type type,ParameterDirection direction) { SqlParameter param=new SqlParameter("@"+name,GetSqlDbType(type)); param.Direction=direction; cmd.Parameters.Add(param); } //在SqlCommand执行前设置参数值 public void SetParameter(SqlCommand cmd,string name,object value) { cmd.Parameters["@"+name].Value=(value==null?DBNull.Value:value); } //在SqlCommand执行后取得参数值 public object GetParameter(SqlCommand cmd,string name) { return cmd.Parameters["@"+name].Value; } //根据不同的返回值执行不同的操作 public SqlDataReader ExecuteDataReader(SqlCommand cmd) { return cmd.ExecuteReader(); } public object ExecuteScalar(SqlCommand cmd) { return cmd.ExecuteScalar(); } public void ExecuteNonQuery(SqlCommand cmd) { cmd.ExecuteNonQuery(); } public DataSet ExecuteDataSet(SqlCommand cmd) { DataSet ds=new DataSet(); using(SqlDataAdapter sda=new SqlDataAdapter(cmd)) { sda.Fill(ds); } return ds; } public DataTable ExecuteDataTable(SqlCommand cmd) { DataTable table=new DataTable(); using(SqlDataAdapter sda=new SqlDataAdapter(cmd)) { sda.Fill(table); } return table; } public DataRow ExecuteDataRow(SqlCommand cmd) { DataTable table=ExecuteDataTable(cmd); if(table.Rows.Count==0) return null; return table.Rows[0]; } } public class StoredProcedure { static public object CreateStoredProcedureInterface(Type interfaceType,SqlConnection connection,SqlTransaction transaction) { //检查参数 if(interfaceType==null)throw(new ArgumentNullException("interfaceType")); if(!interfaceType.IsInterface) &nbs