C# OleDbDataReader读取命令。ExecuteReader();

C# OleDbDataReader读取命令。ExecuteReader();,c#,ms-access,oledbcommand,C#,Ms Access,Oledbcommand,我尝试用access DB编写一个简单的登录表单。 按下登录按钮后,返回代码并标记: OleDbDataReader=command.ExecuteReader() 连接成功,但当我按login时返回 mdb名称:users1.mdb 表名:DataData 图片: 我的代码有什么问题 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using Sy

我尝试用access DB编写一个简单的登录表单。 按下登录按钮后,返回代码并标记:

OleDbDataReader=command.ExecuteReader()

连接成功,但当我按login时返回

mdb名称:users1.mdb 表名:DataData

图片:

我的代码有什么问题

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(); } } }
使用制度; 使用System.Collections.Generic; 使用系统组件模型; 使用系统数据; 使用系统图; 使用System.Linq; 使用系统文本; 使用System.Threading.Tasks; 使用System.Windows.Forms; 使用System.Data.OleDb; 名称空间CDHW { 公共部分类Form1:Form { 专用OleDbConnection connection=新OleDbConnection(); 公共表格1() { 初始化组件(); connection.ConnectionString=@“Provider=Microsoft.Jet.OLEDB.4.0;数据源=C:\Users\RBA\Desktop\123\users1.mdb; 持久化安全信息=False;“; } 私有void Form1\u加载(对象发送方、事件参数e) { 尝试 { connection.Open(); checkConnection.Text=“连接成功”; connection.Close(); } 捕获(例外情况除外) { MessageBox.Show(“错误”+ex); } } 私有void groupBox1_Enter(对象发送方,事件参数e) { } 私有无效btn\u登录\u单击(对象发送者,事件参数e) { connection.Open(); OLEDBCOMAND命令=新的OLEDBCOMAND(); command.Connection=连接; command.CommandText=“从数据数据中选择*,其中用户=”+text_Username.text+”,密码=”+text_Password.text+”; OleDbDataReader=command.ExecuteReader(); 整数计数=0; while(reader.Read()) { 计数=计数+1; //计数++; // } 如果(计数=1) { MessageBox.Show(“Wellcome to G工具”); } 如果(计数=1) { MessageBox.Show(“密码重复”); } 其他的 { MessageBox.Show(“用户名或密码不正确”); } connection.Close(); } } }
注意:请参阅有关转义
用户
密码
的注释

我们首先要考虑的是:参数。现在,如果用户名/密码包含一系列字符,可能会发生非常糟糕的事情;因此:

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));
下一个问题是纯文本密码,但这是一个巨大的领域-只是。。。永远不要将密码存储为文本。。。永远

现在,我假设上面的方法不能解决这个问题;如果是这样,您需要检查数据库中如何定义
用户
密码
。错误消息表明其中一个不是很像文本

这段代码中也有很多
使用
等问题,可能会导致与“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;
}
var userIds=connection.Query(
“从数据数据中选择[用户]=@cn和[密码]=@pw”,
新的{cn=text_Username.text,pw=text_Password.text}).AsList();
开关(userIds.Count){
案例0://TODO:不存在
案例1://TODO:完美
打破
默认值://TODO:oops,多个用户
打破
}

考虑将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;

这样,您就不必遍历所有记录来获得记录计数。

使用块可确保即使出现错误,数据库对象也已关闭并释放。这可以确保清理这些对象使用的非托管资源

您可以将连接字符串直接传递给连接的构造函数。同样,该命令的构造函数可以接受sql语句和连接

使用参数重载。添加使用参数名称和数据类型的。这有助于我们了解参数的值与数据类型匹配

因为我们在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语句中出现的顺序将参数添加到参数集合中。此提供程序将与参数名称不匹配。

command.CommandText=“从数据数据中选择*,其中User='”+text\u Username.text+“'和Password='“+text\u Password.text+”-这行有太多错误,很难知道从哪里开始。。。问:这是一个“真实”的系统,还是仅仅是一个本地玩具?如果是“真实的”,我们需要在这里介绍很多安全方面的内容……我同意Marc的观点,但是看看你的错误信息。您是否拥有与文本类型不同的列用户或列密码?请不要忘记让您的代码能够防止恶意SQL注入。您编写person的方式可以提供包含附加SQL命令的用户名。“从数据数据中选择*,其中用户='”+text_Username.text+“'和密码='”+text_Password.text+“'”;考虑如果提供的用户名是“鲍伯”;从DATABATE中删除*;从DATABATE中选择“用户=”“本地玩具”,将会发生什么。这是怎么回事?这个答案根本无法回答问题中讨论的问题。而且<代码>数据表
不生成代码better@Marc格拉威尔。你有没有费心去看奥默德的照片