一步一步学习Winform系列2:数据绑定(SQLHelper类)

阅读目录:

1、已有Sqlhelper类库的建立和引用

2、App.config配置文件设置

3、sqlhelp类代码解析

4、基本信息维护界面的设计与跳转

本课程需要使用Sqlhelper.cs文件,在基本信息维护界面中需要部分图片素材。你可以在这里下载


 1 已有Sqlhelper类库的建立和引用


为了体现分层的概念,给解决方案新建一个项目(类型为:类库),命名为NorthwindDAL,右键单击这个项目添加一个现有项(这里可以下载SQLhelper.cs),添加后整个项目效果如图。

 

修改SqlHelper的命名空间与项目名称同名,如这里的NorthwindDAL。

 

这时调试系统会提示这样的错误:系统提示上下文不存在ConfigurationManager,原因在于没有引用System. Configuration.dll。

解决方案:在本文件所在的NorthwindDAL引用上右键打开引用对话框,选择引用Net的System.Configuration即可。

 

回到顶部


 2、同时,我们为CSS项目添加了一个配置文件app.config


在CSS项目右键菜单,选择添加新项,选择应用程序配置文件。

 

打开配置文件,为这个xml文件添加一个字符节。注意这里的数据库连接需要改变成你系统自己的字符串

 

View Code
<configuration>
  <configSections>
    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="NorthwindCSS.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    </sectionGroup>
  </configSections>
</configuration>

 

这个文件有什么好处呢?事实上,这是一个XML文件,利用配置节的方式,我们将数据库连接字符串记录在配置节处。每次调用数据库连接时就直接从这个配置文件中获取。如果数据库发生位置或者名称的改变,只需要更改这里的配置节信息就可以了,不需要像上一课中在程序代码中更改。

为了能够调用sqlhelper类文件里面的方法,实现代码的重用,我们需要首先建立起NorthwindCSS与northwindDAL之间的引用关系,其中CSS是引用者,所以在它的右键菜单上添加引用项目。

 

选择项目即可,如果有多个项目引用,那就添加多次。

这时,我们回到Login的代码文件中(因为这里需要使用到sqlhelper)继续加入using语句(Using后面的是它的命名空间,这就是刚刚我们为什么要改名字的原因了),或者直接让VS帮你解析。

 

重写一个自定义的用户验证函数IsValidateBySqlHelper,用以测试是否可以引用sqlparameter来规避注入式攻击。(通过右键菜单“转到定义”可以查看自定义方法,可以使用“转到引用” 学习已有的代码)。

用户验证函数IsValidateBySqlHelper代码与注释。 

View Code
 /// <summary>
        /// 通过调用已有SqlHelper类,验证用户密码是否匹配,同时规避注入式攻击
        /// </summary>
        /// <param name="strUserName">用户名</param>
        /// <param name="strPwd">用户密码</param>
        /// <returns>如果用户密码匹配则返回真</returns>
        public bool IsValidateBySqlHelper(string strUserName, string strPwd)
        {
            //准备参数 
            // <param name="connectionString">一个有效的数据库连接字符串</param>           
            SqlConnection conn = SqlHelper.GetConnection();

            // <param name="commandText">存储过程名或T-SQL语句</param> 
            string strSql = "SELECT * FROM Employees WHERE FirstName=@UserName AND Password=@Pwd";

            // <param name="commandParameters">SqlParamter参数数组(new SqlParameter("@prodid", 24))</param> 
            SqlParameter[] para = new SqlParameter[2];
            para[0] = new SqlParameter("@UserName", SqlDbType.NVarChar);
            para[0].Value = strUserName;
            para[1] = new SqlParameter("@Pwd", SqlDbType.NVarChar);
            para[1].Value = strPwd;

            //直接调用SQLHelper类中的方法
            SqlDataReader reader = SqlHelper.ExecuteReader(conn, CommandType.Text, strSql, para);
            if (reader.HasRows)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

 在原程序中调用这个函数,生成解决方案后运行程序,输入用户名1' or '1'='1,结果如图。我们利用SQLHelper中的Parameter参数组解决了上一课遗留的注入式攻击问题。

 

 

回到顶部

 


延伸知识——SQLHelper函数详解


    SqlHelper的目的是从数据库获得信息或将信息保存到数据库。在 SqlHelper 类中实现的方法包括:

    ExecuteNonQuery。此方法用于执行不返回任何行或值的命令。这些命令通常用于执行数据库更新,但也可用于返回存储过程的输出参数。

  ExecuteReader。此方法用于返回 SqlDataReader 对象,该对象包含由某一命令返回的结果集。

  ExecuteDataset。此方法返回 DataSet 对象,该对象包含由某一命令返回的结果集。

  ExecuteScalar。此方法返回一个值。该值始终是该命令返回的第一行的第一列。

  ExecuteXmlReader。此方法返回 FOR XML 查询的 XML 片段。

  除了这些公共方法外,SqlHelper 类还包含一些专用函数,用于管理参数和准备要执行的命令。不管客户端调用什么样的方法实现,所有命令都通过 SqlCommand 对象来执行。在 SqlCommand 对象能够被执行之前,所有参数都必须添加到 Parameters 集合中,并且必须正确设置 Connection、CommandType、CommandText 和 Transaction 属性。SqlHelper 类中的专用函数主要用于提供一种一致的方式,以便向 SQL Server 数据库发出命令,而不考虑客户端应用程序调用的重载方法实现。SqlHelper 类中的专用实用程序函数包括:

  AttachParameters:该函数用于将所有必要的 SqlParameter 对象连接到正在运行的 SqlCommand。

  AssignParameterValues:该函数用于为 SqlParameter 对象赋值。

  PrepareCommand:该函数用于对命令的属性(如连接、事务环境等)进行初始化。

  ExecuteReader:此专用 ExecuteReader 实现用于通过适当的 CommandBehavior 打开 SqlDataReader 对象,以便最有效地管理与阅读器关联的连接的有效期。

 

    本页面提供下载的SqlHelper主要功能如下:

(1)执行不返回数据的T-Sql命令。例如修改雇员信息、添加部门资料等。

(2)返回一个字段的T-Sql命令。例如获取部门的部门说明。

(3)返回一组数据。例如获取雇员资料、获取所有部门信息等。

(4)缓存参数列表。在执行一条语句时,可能有多个参数,为了提高速度,将参数缓存。

(5)读取缓存的参数。

 

代码详解

为了减少数据库连接字符串的写法,所以我们需要将数据库连接字符串统一写在配置文件内,这一改变环境的时候只需要更改配置文件就可以了。(代码易维护)

//说明1

using System.Configuration;

Using关键字:见代码说明1。Using处理对命名空间的引用。通常,如果系统提示找不到某个类,一定要仔细检查是否引用了这个类的命名空间。

//说明2

/// <summary>

/// 数据库的通用访问代码

/// 此类为抽象类,不允许实例化,在应用时直接调用即可

/// </summary>

(2)注释:见代码说明2。在方法上面一行如果输入“///”,系统会自动将此方法的注释架构搭建好,主要包括Summary和param name。如果方法有返回值,还包括returns;如果需要特殊说明可以使用remarks标志。根据这个结构,可以很容易地描述清楚整个方法的组成及使用方法。在注释中使用“///”,将来在代码调用时,会出现提示,提示的内容就是所添加的注释。

//说明3

    public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)

(3)CommandType的使用:见代码说明3。SQL Server数据处理的两种方法:存储过程和T-SQL语句。每条执行语句都有个参数CommandType,这是个枚举类型,有3个选项:StoredProcedure、TableDirect和Text。它们分别表示存储过程、表和T-SQL语句。如果CommandType参数选择StoredProcedure,则cmdText参数就是存储过程的名字;如果CommandType是Text,则cmdText是SQL语句;如果CommandType是TableDirect,则cmdText是表名称。

//说明4

        using (SqlConnection conn = new SqlConnection(connectionString))

{

…………

}

(4)在Using语句中,用“{}”定义一个范围,在语句完成时释放语句内使用的资源。Using语句通常用在获取数据的方法中,语句的范围是从打开数据库连接开始,到所有使用连接的资源都运行完毕后终止。Using语句可以与多个对象一起使用。使用Using语句的对象必须继承IDispose接口。此接口实现了Dispose方法,该方法才是释放对象资源的执行者。

  //说明8

    private static Hashtable parmCache = Hashtable.Synchronized(new

    Hashtable());//说明9

(8)哈希表表示键/值(key/value)对的组合。通过键值的映射来访问哈希代码。.NET中的哈希表是System.Collections命名空间提供的一个容器,英文名称为HashTable,通过key来实现快速查找,key区分大小写。value存储key对应的值,通常表现为object类型,当取值时要进行相应的类型转换。

(9)private static Hashtable parmCache = Hashtable. Synchronized(new Hashtable( ))这条语句实现了哈希表的同步包装,包装是基于线程安全的。此处的哈希表是static类型的静态变量,既然是static,就是一次定义,全局使用。所有的参数都使用这个哈希表,那如何保证其他人在修改的时候不影响自己的读取呢?以前可以使用lock的方法先锁定表,不允许他人修改,读取完毕后再解锁。现在.NET提供了HashTable的Synchronized方法,实现同样的功能,不需要手动加锁,直接由系统框架完成。

      //说明5

    public static int ExecuteNonQuery(SqlConnection connection, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)

    {

        SqlCommand cmd = new SqlCommand();

        PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);

(5)参数数组:见代码说明5。在C#中不允许使用可选参数,所以参数通常由不指定大小的数组来实现。数组中参数的添加由PrepareCommand方法完成。

    //说明12

    public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType,

string cmdText, params SqlParameter[] commandParameters)

(12)方法重载:见代码说明12。定义了两个或多个具有相同名称但参数不同的方法。在SqlHelper中,ExcuteNonQuery被重载了4次,通过代码中的注释可以很清楚地看出参数列表的不同。在实际应用中,根据功能环境调用相应的方法。

    //说明13   

/// <summary>

        /// 一个有效的数据库连接字符串

        /// </summary>         

        public static string GetConnSting()

        {

            return ConfigurationManager.ConnectionStrings["strConn"].ConnectionString.ToString();

                  }

(13)ConfigurationManager是ASP.NET 2.0中新加的一个类,主要对Web.config文件进行管理。可以轻松获取在Web.config文件中定义的配置,通常用来获取数据库连接字符串和个性化配置信息。在Winfrom程序中如果需要动态配置app.config ,则右击项目名称,选择“添加”→“添加新建项”,在出现的“添加新项”对话框中,选择“添加应用程序配置文件”;如果项目以前没有配置文件,则默认的文件名称为“app.config”,单击“确定”。

App.config文件还可以进行动态删除修改,具体操作:http://blog.163.com/muyao520@126/blog/static/69555456201092311018824/

 

 //说明14       return val

(14)ExcuteNonQuery方法的返回值:见代码说明14。在SqlCommand的方法中,ExcuteNonQuery用来执行插入、更新或删除等操作。程序并不要求有任何返回值,但在SqlHelper中定义此方法时返回了一个数值型数据。该数据用来表示执行当前语句后数据库中被影响的行数。虽然在此定义了返回值,但在程序的调用中,可以不用返回值,直接执行方法。例如:SqlHelper. ExcuteNonQuery( )就是正确的,不一定非要写成 int val= SqlHelper. ExcuteNonQuery( )。如果程序中需要的不是int值,还可以进行转换。

       //说明7

Try

{

……

}       

catch

        {

            conn.Close();

            throw;

}

(7)throw:见代码说明7。再次引发捕获的异常,目的是向文本中添加异常处理信息。如果要引发异常,throw和catch一定要搭配使用,如果catch有参数,则throw也要带参数,相反亦然。

       //说明10  parmCache[cacheKey] = commandParameters;

(10)缓存参数列表:见代码说明10。缓存参数列表就是将参数信息保存在已经定义的静态HashTable中。因为HashTable是静态的,一旦定义,就分配了内存地址,在项目中随时都可以使用,起到了缓存数据的作用。

          //说明11   clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).

Clone();

(11)clone:克隆。见代码说明11。在.NET中,几乎所有继承Collections类的集合都具有clone的方法。在获取缓存参数的方法中有下面这句代码:clonedParms[i] = (SqlParameter) ((ICloneable)cachedParms[i]).Clone( )。因为所有的参数都保存在一个HashTable中,表中保存的只是参数的名字,而参数的内容则是由不同的调用给予不同的值。为了正确反映调用者的值,必须克隆出一个参数列表,由调用者根据功能赋予对应的值。

    //说明6

    private static void PrepareCommand(SqlCommand cmd, SqlConnection conn,

SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[]
         cmdParms)

(6)SQL事务处理:见代码说明6。事务是指一组相关联的操作。在事务处理时,通常锁住相关的表,等事务处理完成后才解锁,这样保证了数据的完整性。事务一般包括3个方法:开始事务、执行事务和事务回滚(RollBack)。如果事务中的一条语句出现问题,则事务回滚,其他语句的执行也被取消。

回到顶部


4、基本信息维护界面的设计与跳转


为CSS项目添加一个文件夹,文件夹命名为基本信息管理,新建一个Windows窗体,命名为基本信息维护主界面,界面内控件设置如下

 

找到Login界面中登陆成功跳转窗口的位置,输入

Form BaseInfo= new 基本信息管理主界面 ();

BaseInfo.Show();

This.Hide();//隐藏本窗体

 这是登陆按钮的点击事件代码如下:

View Code
      //登陆按钮的单击事件
        private void btnLogin_Click(object sender, EventArgs e)
        {
            //进行输入验证
            if (tbxUsername.Text == "请输入用户名" || tbxUsername.Text == "")
            {
                MessageBox.Show("用户名不能为空!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tbxUsername.Focus();
            }
            else if (tbxPwd.Text == "")
            {
                MessageBox.Show("密码不能为空!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tbxPwd.Focus();
            }
            else if (IsValidateBySqlHelper(tbxUsername.Text.Trim(), tbxPwd.Text.Trim()))
            {
                // MessageBox.Show("验证通过,欢迎你," + tbxUsername.Text, "登陆成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                MessageBox.Show("验证通过,欢迎你," + tbxUsername.Text, "登陆成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
               // MessageBox.Show("欢迎你," + tbxUsername.Text + " ,你的头衔是" + GetTitleByUserName(tbxUsername.Text), "登陆成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
               
                //跳转到新窗口,待续。。。。
               Form mainForm= new MainForm(tbxUsername.Text,GetTitleByUserName(tbxUsername.Text));
               mainForm.Show();
               this.Hide();

                //修改于2013-2-21 添加外部属性:用于全程记录登陆的职工ID
               CommonFunc.str雇员名称 = tbxUsername.Text;
            }
            else
            {
                MessageBox.Show("用户密码不匹配,请重新输入!", "登陆失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tbxUsername.Text = String.Empty;
                tbxPwd.Text = String.Empty;
            }
        }

 

这时VS会提示你需要解析(using语句),右键菜单解析后自动添加using语句

 

运行本程序,登陆成功后自动跳转到基本信息管理主界面。

下节课我们会结合DataGridview讲解部门信息管理、雇员信息管理记录的增删改查。

 

posted @ 2013-03-05 21:34  森-Pirate  阅读(1450)  评论(0编辑  收藏  举报