OleDbDataReader 读取 command.ExecuteReader();
OleDbDataReader reading command.ExecuteReader();
我尝试用访问数据库编写一个简单的登录表单。
在我按下登录按钮后,它的 return 进行编码并标记为:
OleDbDataReader reader= command.ExecuteReader();
连接成功但是当我按下登录时 return。
mdb 名称: users1.mdb
table 名称: 数据数据
图片:
https://imgur.com/a/gl2Xfga
我的代码有什么问题?
</p>
<pre>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\Desktop3\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();
}
}
}
注意:请参阅重新转义 User
和 Password
的注释。
这里首先要考虑的是:参数。现在,如果 username/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
等问题,可能导致与 "open reader" 等相关的奇怪错误;如果可能的话,我强烈推荐一个像 Dapper 这样的工具,它可以使正确编写此类代码变得容易得多。例如:
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;
}
考虑使用带有 DataTable 的 OleDbDataAdapter。
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;
这样您就不必遍历所有记录来获取记录数。
即使出现错误,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\Desktop3\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 语句中出现的相同顺序将参数添加到参数集合中。此提供程序将不匹配参数名称。
我尝试用访问数据库编写一个简单的登录表单。 在我按下登录按钮后,它的 return 进行编码并标记为:
OleDbDataReader reader= command.ExecuteReader();
连接成功但是当我按下登录时 return。
mdb 名称: users1.mdb table 名称: 数据数据
图片: https://imgur.com/a/gl2Xfga
我的代码有什么问题?
</p>
<pre>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\Desktop3\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();
}
}
}
注意:请参阅重新转义 User
和 Password
的注释。
这里首先要考虑的是:参数。现在,如果 username/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
等问题,可能导致与 "open reader" 等相关的奇怪错误;如果可能的话,我强烈推荐一个像 Dapper 这样的工具,它可以使正确编写此类代码变得容易得多。例如:
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;
}
考虑使用带有 DataTable 的 OleDbDataAdapter。
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;
这样您就不必遍历所有记录来获取记录数。
即使出现错误,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\Desktop3\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 语句中出现的相同顺序将参数添加到参数集合中。此提供程序将不匹配参数名称。