1.需求分析:做一个登录的小程序,基于Winform的窗体小程序。基本要求:登录成功:弹框显示登录成功,登录失败就弹框显示失败。

扩展功能:登录次数超过3次,就”锁定“用户,提示登录错误次数过多,不能登录。用户点击之后,就退出程序;登录成功,就把错误字段清零。

这里我们在数据库表中,加一个错误字段,类型为int,初始值设置为0.

相信;这个小程序对于大家来说,是超级简单的。我这里也是来熟悉一下,把基础知识再巩固一下。

2.用到的技术:ADO.NET,存储过程。

3.项目实现:

  • 首先我们新建一个窗体应用程序,然后把该有的控件,放上去,如图所示:

  • 创建数据库和存储过程:
  •  USE [DB_USERS]
     GO
    
     /****** Object:  Table [dbo].[T_USERS]    Script Date: 06/07/2015 17:48:33 ******/
     SET ANSI_NULLS ON
     GO
    
     SET QUOTED_IDENTIFIER ON
     GO
    
     CREATE TABLE [dbo].[T_USERS](
         [T_ID] [INT] IDENTITY(,) NOT NULL,
         [T_NAME] [NVARCHAR]() NOT NULL,
         [T_PWD] [NVARCHAR]() NOT NULL,
         [T_AGE] [INT] NOT NULL,
         [T_ErrorTimes] [INT] NOT NULL,
     PRIMARY KEY CLUSTERED
     (
         [T_ID] ASC
     )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
     ) ON [PRIMARY]
    
     GO

    数据库脚本

*数据库表是我之前建好的,现在就直接导成脚本算了。现在来写存储过程

*根据用户名来查询信息(因为之前,我写了根据用户名来查询用户信息,但是现在我给之前写的存储过程改个名字)

我们可以使用:EXEC sp_rename '旧名', '新名',

这里我就不贴根据用户名,来查询用户信息的存储过程了,可以看我前面几个系列的文章。

*用户输入错误,给错误字段自增1的存储过程:

  IF OBJECT_ID('Incre_errorTimes','P') IS NOT NULL
  DROP PROCEDURE Incre_errorTimes
  GO
  CREATE PROCEDURE Incre_errorTimes
  @userName nvarchar()
  AS
  UPDATE dbo.T_USERS SET T_ErrorTimes=T_ErrorTimes+ WHERE T_NAME=@userName
  GO
  

*用户输入正确,给错误字段的值设置为0

  IF OBJECT_ID('Reset_errorTimes','P') IS NOT NULL
  DROP PROCEDURE Reset_errorTimes
  GO
  CREATE PROCEDURE Reset_errorTimes
  @userName nvarchar()
  AS
  UPDATE dbo.T_USERS SET T_ErrorTimes= WHERE T_NAME=@userName
  GO
  

数据库表,和存储过程弄好之后,我们可以来写程序了

这里的连接字符串,我放在配置文件中,具体怎么操作,就不再赘述了。

编码实现:

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using System.Data;
 using System.Data.SqlClient;

 namespace 窗体的登录程序
 {
     public partial class Login : Form
     {
         public Login()
         {
             InitializeComponent();
         }
         /// <summary>
         /// 增加错误次数
         /// </summary>
         public void IncerErrTimes(string sql, params SqlParameter[] parmeters)
         {
             //1创建连接对象
             SqlConnection scon = new SqlConnection(DBHelper.GetConnectString());
             //2创建命令对象
             SqlCommand scmd = new SqlCommand();
             scmd.CommandText = sql;
             scmd.CommandType = CommandType.StoredProcedure;
             scmd.Connection = scon;
             //3打开连接
             scon.Open();

             //配置参数
             foreach (SqlParameter item in parmeters)
             {
                 scmd.Parameters.Add(item);

             }

             //4执行命令
             //5.处理数据
            scmd.ExecuteNonQuery();

             //6关闭连接
             scon.Close();

         }

         /// <summary>
         /// 充置错误次数
         /// </summary>
         public void ResetErrTimes(string sql, params SqlParameter[] parmeters)
         {
             //1创建连接对象
             SqlConnection scon = new SqlConnection(DBHelper.GetConnectString());
             //2创建命令对象
             SqlCommand scmd = new SqlCommand();
             scmd.CommandText = sql;
             scmd.CommandType = CommandType.StoredProcedure;
             scmd.Connection = scon;
             //3打开连接
             scon.Open();

             //配置参数
             foreach (SqlParameter item in parmeters)
             {
                 scmd.Parameters.Add(item);

             }
             //4执行命令
             //5.处理数据
             scmd.ExecuteNonQuery();

             //6关闭连接
             scon.Close();

         }

         private void btnLogin_Click(object sender, EventArgs e)
         {
             //获取用户输入的用户名和密码
             string usernName = txtLoginName.Text.Trim();
             string password = txtPassword.Text.Trim();

             //连接方式访问数据库

             //1.创建连接对象(连接字符串)
             SqlConnection scon = new SqlConnection(DBHelper.GetConnectString());

             //2创建命令对象
             SqlCommand scmd = new SqlCommand();
             scmd.CommandText = "GetUserInfoByName";
             scmd.CommandType = CommandType.StoredProcedure;
             scmd.Connection = scon;

             //3打开连接
             scon.Open();

             //配置参数
             SqlParameter parameter = new SqlParameter();
             parameter.ParameterName = "@name";
             parameter.DbType = DbType.String;
             parameter.Value = usernName;
             parameter.Direction = ParameterDirection.Input;
             scmd.Parameters.Add(parameter);

             //4执行命令
             SqlDataReader reader = scmd.ExecuteReader(CommandBehavior.CloseConnection);

             //5.处理数据。
             if (reader.Read())
             {
                 int errorTimes =(int)reader["T_ErrorTimes"];
                 )
                 {
                     MessageBox.Show("登录错误次数过多", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                     return;
                 }

                 if (password == reader.GetString(reader.GetOrdinal("T_PWD")))
                 {
                     MessageBox.Show("登录成功", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                     ResetErrTimes("Reset_errorTimes", new SqlParameter("@userName", usernName));

                 }
                 else
                 {
                     MessageBox.Show("密码错误", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                     IncerErrTimes("Incre_errorTimes", new SqlParameter("@userName", usernName));

                 }
             }
             else
             {
                 MessageBox.Show("用户名不存在", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
             }

             //6.关闭连接
             reader.Close();

         }
     }
 }

编码实现

实现这个功能的过程中,遇到了几个问题:

1.创建存储过程的时候,使用的参数是@userName。而根据用户名查询用户的信息的存储过程只用的参数是@name,这两个搞混了,应该分开来。。

2.创建一个封装查询的方法  public void ResetErrTimes(string sql, params SqlParameter[] parmeters)和  public void IncerErrTimes(string sql, params SqlParameter[] parmeters)的时候,写成了 public void ResetErrTimes(string sql, params string[] parmeters)导致后面调用这个方法的时候,报错。

3.循环添加参数的时候,写错了,我之前写成了:

foreach (var item in parmeters)
{
scmd.Parameters.Add(parmeters);    //这是错误的。

}

4.存储过程的改名:EXEC sp_rename '旧名', '新名'

正确的应该是:

foreach (SqlParameter item in parmeters)
{
scmd.Parameters.Add(item);

}

程序执行的效果图:

总的来说,通过做这个例子,我收获很大。大家呢?

ADO.NET学习系列(四)---窗体版的登录小程序的更多相关文章

  1. scrapy爬虫学习系列四:portia的学习入门

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

  2. DocX开源WORD操作组件的学习系列四

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  3. .net reactor 学习系列(四)---.net reactor应用场景

    原文:.net reactor 学习系列(四)---.net reactor应用场景         前面已经学习了.net reactor一些基础知识,现在准备学习下实际的应用场景,只是简单的保护和 ...

  4. Java生鲜电商平台-关于学习生鲜电商平台的思考(小程序/APP)

    Java生鲜电商平台-关于学习生鲜电商平台的思考(小程序/APP) 说明:最近群里面的一个网友问的一个问题,让我陷入了深思,他问的问题很基础也很真实,"大佬,你们是怎么学习的呢?" ...

  5. Identity Server4学习系列四之用户名密码获得访问令牌

    1.简介 Identity Server4支持用户名密码模式,允许调用客户端使用用户名密码来获得访问Api资源(遵循Auth 2.0协议)的Access Token,MS可能考虑兼容老的系统,实现了这 ...

  6. 微信小程序学习笔记(一)--创建微信小程序

    一.创建小程序 1.申请帐号.安装及创建小程序,请参照官方文档里面的操作 https://developers.weixin.qq.com/miniprogram/dev/. 小程序在创建的时候会要求 ...

  7. MVC3+EF4.1学习系列(四)----- ORM关系的处理

    上篇文章 终于把基础的一些操作写完了 但是这些都是单表的处理 而EF做为一个ORM框架  就必须点说说对于关系的处理 处理好关系 才能灵活的运用EF 关于关系的处理 一般就是  一对一   一对多  ...

  8. Vue学习系列(四)——理解生命周期和钩子

    前言 在上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发.而在这一篇中,我们将通过 ...

  9. WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】

    WCF Interview Questions – Part 4   This WCF service tutorial is part-4 in series of WCF Interview Qu ...

随机推荐

  1. MYSQL INSERT INTO SELECT 不插入重复数据

    INSERT INTO `b_common_member_count` (uid) SELECT uid FROM `b_common_member` WHERE uid NOT IN (SELECT ...

  2. nodejs express 框架解密4-路由

    本文档是基于express3.4.6 express 的路由是自己去实现的,没有使用connect中的路由中间件模块. 1.在如何创建一个app那篇中,我们提到了路由, //router //路由 t ...

  3. <《基金经理投资笔记丛书4-1:投资是一种生活方式》>

    在中国股市每年能获得10%的收益已经是非常好了,但问题是大多数股民不认为这是一个很高的收益水平,尽管现实中大多数股民的收益状况比这要差很多. 投资中一个重要的心理陷阱是过度自信,过度自信的一个主要表现 ...

  4. Eclipse远程调试HDP源代码

    使用的是自己编译的HDP2.3.0的源代码编译的集群,此文介绍如何使用Eclipse远程调试Hadoop内核源代码,以调试namenode为例进行介绍. 在/usr/hdp/2.3.0.0-2557/ ...

  5. Oracle 数据库表同步方法浅议

    总结一下Oracle数据库表级别的复制同步 一.通过触发器进行表的复制 原理,是监听表上都某一字段进行的DML操作,然后得到DML操作的数据,重新在另一个表上执行DML操作. 优点: 简单,编写一个触 ...

  6. Spark源码系列(七)Spark on yarn具体实现

    本来不打算写的了,但是真的是闲来无事,整天看美剧也没啥意思.这一章打算讲一下Spark on yarn的实现,1.0.0里面已经是一个stable的版本了,可是1.0.1也出来了,离1.0.0发布才一 ...

  7. HTML5新特性之WebSocket

    1.概述 HTTP协议是一种无状态协议,服务端本身不具有识别客户端的能力,必须借助外部机制,比如session和cookie,才能与特定客户端保持对话.这多多少少带来一些不便,尤其在服务器端与客户端需 ...

  8. java&postgresql时区总结

    介绍这篇文章之前,首先回答一个问题,以前都没有时区的概念,程序也写的好好的,为什么要计算时区哪?举个例子,比如有一个订单的时间是:2015-07-04 11:28:19,那么咋一看没什么问题,可是如果 ...

  9. 【转载】JDBC连接各种数据库的字符串

    oracle    driverClass:oracle.jdbc.driver.OracleDriver    url:jdbc:oracle:thin:@127.0.0.1:1521:dbname ...

  10. JAVA & JSON详解

    JSON定义 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类 ...