我尝试使用Access DB编写一个简单的登录表单。 在我按下登录按钮后,返回代码并标记为:
OleDbDataReader reader = command.ExecuteReader();
连接成功,但是当我按登录键返回时。
mdb名称: users1.mdb 表名: DataData
图片: https://imgur.com/a/gl2Xfga
我的代码有什么问题?
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.OleDb;
namespace CDHW
{
public partial class Form1 : Form
{
private OleDbConnection connection = new OleDbConnection();
public Form1()
{
InitializeComponent();
connection.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source = C:\Users\RBA\Desktop\123\users1.mdb;
Persist Security Info=False;";
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
connection.Open();
checkConnection.Text = "Connection Successful";
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void btn_Login_Click(object sender, EventArgs e)
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "select * from DataData where User='" + text_Username.Text + "' and Password='" + text_Password.Text + "'";
OleDbDataReader reader= command.ExecuteReader();
int count = 0;
while (reader.Read())
{
count = count + 1;
//count++;
//
}
if (count == 1)
{
MessageBox.Show("Wellcome to G Tool");
}
if (count == 1)
{
MessageBox.Show("Password is duplicated");
}
else
{
MessageBox.Show("User Name or Password is incorrect");
}
connection.Close();
}
}
}
答案 0 :(得分:2)
请注意:请参见注释重新转义Password
和command.CommandText = "select * from DataData where [User]=@cn and [Password]=@pw";
command.Parameters.Add(new OleDbParameter("@cn", text_Username.Text));
command.Parameters.Add(new OleDbParameter("@pw", text_Password.Text));
。
我们在这里应该考虑的第一件事是:参数。现在,如果用户名/密码包含一定范围的字符,则可能会发生非常糟糕的事情。所以:
User
下一个问题是纯文本密码,但这是一个很大的领域-只是...永远不要将密码存储为文本...
现在,我将假设上面的 不能解决该问题;如果是这样,则需要检查如何在数据库中定义Password
和using
。错误消息表明其中一个不是很像文本。
此代码中还存在许多var userIds = connection.Query<string>(
"select [User] from DataData where [User]=@cn and [Password]=@pw",
new { cn = text_Username.Text, pw = text_Password.Text }).AsList();
switch(userIds.Count) {
case 0: // TODO: doesn't exist
case 1: // TODO: perfect
break;
default: // TODO: oops, multiple users
break;
}
等问题,可能会导致与“开放阅读器”等相关的奇怪错误;如果可能的话,我强烈建议您使用Dapper之类的工具,这将使正确编写此类代码变得容易得多。例如:
var email = "youremail@gmail.com",
size = 80;
yourImg.src = 'http://www.gravatar.com/avatar/' + MD5(email) + '.jpg?s=' + size;
答案 1 :(得分:0)
考虑改用OleDbDataAdapter和DataTable。
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = "select * ... ";
DataTable zDataTable = new DataTable;
OleDbDataAdapter zDataAdapter = new OleDbDataAdapter;
zDataAdapter.SelectCommand = command;
zDataAdapter.Fill(zDataTable);
int RecordCount = DataTable.Rows.Count;
这样,您就不必遍历所有记录来获取记录数。
答案 2 :(得分:0)
using块确保即使发生错误,数据库对象也被关闭和处置。这样可以确保清除这些对象使用的非托管资源。
您可以将连接字符串直接传递给连接的构造函数。同样,命令的构造函数可以采用sql语句和连接。
使用Parameters.Add的重载,该重载采用参数名称和数据类型。这有助于使我们知道该参数的值与数据类型匹配。
由于我们在select语句中使用了Count,因此我们可以使用ExecuteScalar,并且只提取单个数据而不是整个记录。
当然,在真实的应用程序中,您永远不会将密码存储为纯文本。
private void button1_Click(object sender, EventArgs e)
{
int RetVal;
using (OleDbConnection connection = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source = C:\Users\RBA\Desktop\123\users1.mdb;Persist Security Info=False;"))
{
using (OleDbCommand cmd = new OleDbCommand("Select Count(*) From DataData Where [user] = @User And [password] = @password;", connection))
{
cmd.Parameters.Add("@User", OleDbType.VarChar).Value = text_Username.Text;
cmd.Parameters.Add("@Password", OleDbType.VarChar).Value = text_Password.Text;
connection.Open();
RetVal = (int)cmd.ExecuteScalar();
}
}
if (RetVal == 1)
MessageBox.Show("Welcome");
else
MessageBox.Show("Login incorrect");
}
差点忘了!使用OleDb提供程序,必须以与sql语句中出现的顺序相同的顺序将参数添加到参数集合。此提供程序将不匹配参数名称。