[英]OleDbDataReader reading command.ExecuteReader();
Im try to write a simple Login Form with access DB. 我尝试用Access DB编写一个简单的登录表单。 after i press login button its return to code and mark this: 在我按下登录按钮后,返回代码并标记为:
OleDbDataReader reader= command.ExecuteReader(); OleDbDataReader reader = command.ExecuteReader();
the connection is successful but when i press login its return. 连接成功,但是当我按登录键返回时。
mdb name: users1.mdb table name: DataData mdb名称: users1.mdb 表名称: DataData
image: https://imgur.com/a/gl2Xfga 图片: https : //imgur.com/a/gl2Xfga
what my problem with my code? 我的代码有什么问题?
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();
}
}
}
Note: see comments re escaping User
and Password
. 注意:请参阅有关重新转义User
和Password
注释。
The first thing we should consider here is: parameters. 我们在这里应该考虑的第一件事是:参数。 Right now, if the username/password contain a range of characters, very bad things can happen; 现在,如果用户名/密码包含一定范围的字符,则可能会发生非常糟糕的事情。 so: 所以:
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));
The next problem is plain text passwords, but that's a huge area - just... don't ever store passwords as text... ever. 下一个问题是纯文本密码,但这是一个很大的领域-只是……永远不要将密码存储为文本……永远。
Now, I'm going to assume that the above doesn't fix it; 现在,我会认为上面并没有解决它; if so, you need to check how User
and Password
are defined in the database. 如果是这样,则需要检查如何在数据库中定义User
和Password
。 The error message suggests that one of them isn't very text-like. 错误消息表明其中之一不是很像文本的。
There's also a lot of using
etc problems in this code which could lead to odd errors related to "open reader" etc; 还有很多using
此代码可能导致与“开放读者”等奇怪的错误等问题; if possible, I strongly recommend a tool like Dapper, which will make it a lot easier to get this kind of code right. 如果可能的话,我强烈建议您使用Dapper之类的工具,这将使正确编写此类代码变得容易得多。 For example: 例如:
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;
}
Consider using a OleDbDataAdapter with a DataTable instead. 考虑将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;
This way you will not have to iterate through all the records to get the record count. 这样,您就不必遍历所有记录来获取记录计数。
The using blocks ensure that you database objects are closed and disposed even it there is an error. using块确保即使发生错误,数据库对象也被关闭和处置。 This insures that unmanaged resources used by these objects are cleaned up. 这样可以确保清除这些对象使用的非托管资源。
You can pass the connection string directly to the constructor of the connection. 您可以将连接字符串直接传递给连接的构造函数。 Likewise the constructor of the command can take the sql statement and the connection. 同样,命令的构造函数可以采用sql语句和连接。
Use the overload of the Parameters.Add that takes the parameter name and the datatype. 使用带有参数名称和数据类型的Parameters.Add的重载。 This helps keep us aware that the value of the parameter matches the datatype. 这有助于使我们知道参数的值与数据类型匹配。
Since we used Count in the select statement we can use ExecuteScalar and only bring down a single piece of data rather than the entire record. 由于我们在select语句中使用了Count,因此我们可以使用ExecuteScalar,并且只提取单个数据而不是整个记录。
Of course in a real application you would NEVER store passwords as plain text. 当然,在实际的应用程序中,您永远不会将密码存储为纯文本格式。
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");
}
Almost forgot! 差点忘了! With the OleDb provider the Parameters must be added to the parameters collection in the same order that they appear in the sql statement. 使用OleDb提供程序,必须以与sql语句中出现的顺序相同的顺序将参数添加到参数集合。 This provider will not match parameter names. 此提供程序将不匹配参数名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.