ADO.NET学习系列(四)---窗体版的登录小程序
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学习系列(四)---窗体版的登录小程序的更多相关文章
- scrapy爬虫学习系列四:portia的学习入门
系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...
- DocX开源WORD操作组件的学习系列四
DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...
- .net reactor 学习系列(四)---.net reactor应用场景
原文:.net reactor 学习系列(四)---.net reactor应用场景 前面已经学习了.net reactor一些基础知识,现在准备学习下实际的应用场景,只是简单的保护和 ...
- Java生鲜电商平台-关于学习生鲜电商平台的思考(小程序/APP)
Java生鲜电商平台-关于学习生鲜电商平台的思考(小程序/APP) 说明:最近群里面的一个网友问的一个问题,让我陷入了深思,他问的问题很基础也很真实,"大佬,你们是怎么学习的呢?" ...
- Identity Server4学习系列四之用户名密码获得访问令牌
1.简介 Identity Server4支持用户名密码模式,允许调用客户端使用用户名密码来获得访问Api资源(遵循Auth 2.0协议)的Access Token,MS可能考虑兼容老的系统,实现了这 ...
- 微信小程序学习笔记(一)--创建微信小程序
一.创建小程序 1.申请帐号.安装及创建小程序,请参照官方文档里面的操作 https://developers.weixin.qq.com/miniprogram/dev/. 小程序在创建的时候会要求 ...
- MVC3+EF4.1学习系列(四)----- ORM关系的处理
上篇文章 终于把基础的一些操作写完了 但是这些都是单表的处理 而EF做为一个ORM框架 就必须点说说对于关系的处理 处理好关系 才能灵活的运用EF 关于关系的处理 一般就是 一对一 一对多 ...
- Vue学习系列(四)——理解生命周期和钩子
前言 在上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发.而在这一篇中,我们将通过 ...
- WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】
WCF Interview Questions – Part 4 This WCF service tutorial is part-4 in series of WCF Interview Qu ...
随机推荐
- CDH的几个包的下载地址
https://archive.cloudera.com/cdh5/parcels/5.3.0/ http://archive.cloudera.com/cm5/installer/5.3.0/ ht ...
- SSH使用教程( Bitvise Tunnelier+Chrome+Proxy Switchy)
前言 网上很多讲解使用Bitvise Tunnelier+Chrome+Proxy Switchy进行SSHFQ操作的教材有所缺失的部分,不太全面,这里重新整理. 本篇博客的主要内容如下: 准备工作 ...
- Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- VirtualBox不能为虚拟电脑 Ubuntu 打开一个新任务
今天在用Vbox中的Ubuntu系统准备测试Python代码时,Vbox报了一个错误:"不能为虚拟电脑 Ubuntu 打开一个新任务".因为之前用的时候还好好的,也不知道是不是最近 ...
- 卖萌的极致!脸部捕捉软件FaceRig让你化身萌宠
FaceRig是一款以摄像头为跟踪设备捕捉用户脸部动作并转化为数据套用在其他动画模型上的一款软件,能够应用于一些日常的视频社交软件或网站,比如视频通话软件Skype和直播网站Twitch.FaceRi ...
- PopupWindow错误:PopupWindow$1.onScrollChanged 出现 NullPointerException和PopupViewContainer.dispatchKeyEvent 出现 NullPointerException
错误1: java.lang.NullPointerException at android.widget.PopupWindow$1.onScrollChanged(PopupWindow.java ...
- 理解netty对protocol buffers的编码解码
一,netty+protocol buffers简要说明 Netty是业界最流行的NIO框架之一优点:1)API使用简单,开发门槛低:2)功能强大,预置了多种编解码功能,支持多种主流协议:3)定制能力 ...
- vim中多标签和多窗口的使用
用vim进行编辑的时候常常因为要编辑多个文件或者是编辑一个文件要参考其他文件而烦恼,这里介绍两种方法: 1.多标签 直接在编辑的时候输入: vim -p 要编辑的文件名 如vim -p * 就是编辑当 ...
- fedora Server 21 安装 Opera 29.0.1795.47
最新文章:Virson's Blog 安装源: yum localinstall --nogpgcheck http://mirror.yandex.ru/fedora/russianfedora/r ...
- SCRIPT1010: 缺少标识符 常见原因
SCRIPT1010: 缺少标识符 ,一般是在IE下会出现这个问题. 今天在调试一段js代码时,在chrome,ff下均正常,但是在IE下就是一直这样的提示,出现这个问题的原因主要有以下几点: 1.出 ...