不支持关键字:尝试打开SQL连接时为'provider'

问题描述 投票:0回答:1

我是C#和SQL的新手,所以非常感谢您的帮助和建议。

我的想法是通过SQL连接到DB,选择密码和电子邮件,然后通过e-mail(SMTP连接)将其发送给想要恢复帐户密码的人。 )。

我的问题是,我试图通过SQL为C#项目设置密码恢复选项,但是出现以下错误:[[错误:“不支持的关键字:'provider'。

这是我的app.config文件:

<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> </configSections> <connectionStrings> <add name="Sales_and_Inventory_System__Gadgets_Shop_.Properties.Settings.POS_DBConnectionString" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\bin\Debug\POS_DB.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" /> <add name="Restaurant_Management_System.Properties.Settings.SIS_DBConnectionString" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\bin\Debug\SIS_DB.accdb" providerName="System.Data.OleDb" /> <add name="Restaurant_Management_System.Properties.Settings.POS_DBConnectionString" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\bin\Debug\POS_DB.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" /> <add name="Restaurant_Management_System.Properties.Settings.RMS_DBConnectionString" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\bin\Debug\RMS_DB.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" /> </connectionStrings> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data></configuration>

这是我的密码恢复类文件:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using System.Net.Mail; namespace Restaurant_Management_System { public partial class frmRecoveryPassword : MetroFramework.Forms.MetroForm { String cs = "Provider=Microsoft.ACE.Sql.12.0;Data Source=|DataDirectory|\\SIS_DB.accdb;"; public frmRecoveryPassword() { InitializeComponent(); } private void RecoveryPassword_Load(object sender, EventArgs e) { txtEmail.Focus(); } private void RecoveryPassword_FormClosing(object sender, FormClosingEventArgs e) { this.Hide(); frmLogin frm = new frmLogin(); frm.txtUserName.Text = ""; frm.txtPassword.Text = ""; frm.txtUserName.Focus(); frm.Show(); } private void timer1_Tick(object sender, EventArgs e) { Cursor = Cursors.Default; timer1.Enabled = false; } private void metroTile1_Click(object sender, EventArgs e) { if (txtEmail.Text == "") { MessageBox.Show("Enter your email", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); txtEmail.Focus(); return; } try { Cursor = Cursors.WaitCursor; timer1.Enabled = true; DataSet ds = new DataSet(); SqlConnection con = new SqlConnection(cs); con.Open(); SqlCommand cmd = new SqlCommand("SELECT User_Password FROM Registration Where Email = '" + txtEmail.Text + "'", con); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(ds); con.Close(); if (ds.Tables[0].Rows.Count > 0) { MailMessage Msg = new MailMessage(); // Sender e-mail address. Msg.From = new MailAddress("[email protected]"); // Recipient e-mail address. Msg.To.Add(txtEmail.Text); Msg.Subject = "Your Password Details"; Msg.Body = "Your Password: " + Convert.ToString(ds.Tables[0].Rows[0]["user_Password"]) + ""; Msg.IsBodyHtml = true; // your remote SMTP server IP. SmtpClient smtp = new SmtpClient(); smtp.Host = "smtp.gmail.com"; smtp.Port = 587; smtp.Credentials = new System.Net.NetworkCredential("[email protected]", "abcd"); smtp.EnableSsl = true; smtp.Send(Msg); MessageBox.Show(("Password Successfully sent " + ("\r\n" + "Please check your mail")), "Thank you", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Hide(); frmLogin LoginForm1 = new frmLogin(); LoginForm1.Show(); LoginForm1.txtUserName.Text = ""; LoginForm1.txtPassword.Text = ""; LoginForm1.ProgressBar1.Visible = false; LoginForm1.txtUserName.Focus(); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void metroTile2_Click(object sender, EventArgs e) { this.Close(); } } }

c# sql sqlconnection
1个回答
0
投票
您的帖子正文中有五个(5!)连接字符串。您正在使用的唯一代码是在frmRecoveryPassword类中硬编码为cs字段的代码。

SqlConnection抱怨,因为它无法识别至少一个名称/值对。这是因为它是OLEDB的连接字符串,而不是SQL Server。

根据您发布的内容,您似乎正在尝试连接到Access数据库。为此,您需要使用OleDbConnection。但是,根据评论,事实并非如此。您确实要连接到SQL Server数据库,因此SqlConnection是正确的,而您的[[连接字符串是错误的。

从您发布的内容开始(而不是此后所做的更改),您唯一需要更改的是此行:

SqlConnection con = new SqlConnection(cs);

将其更改为此:

// Pick one of the three names in app.config that refers to a SQL Server database.
// I chose the first one for this example.
string connectionStringName = "Sales_and_Inventory_System__Gadgets_Shop_.Properties.Settings.POS_DBConnectionString";

string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

SqlConnection con = new SqlConnection(connectionString);

这将通过connectionStringName中指定的名称检索连接,并将其赋予SqlConnection

请确保您为此点击处理程序正在使用正确的连接字符串。

连接字符串


现在让我们检查连接字符串。

app.config中的那些看起来正确,因为它们在每个中指定的providerName属性具有正确的值。第二个指向Access数据库,另外三个指向SQL Server数据库。

屏幕快照中的一个(来自注释)是错误的。它是混合的:您已经指定了OleDb提供程序(用于Access)和SQL Server数据库文件。似乎您从app.config中的第一个连接字符串复制了.mdf文件的路径,并在第二个.accdb文件所在的位置使用了该路径。 SqlConnection将为您提供与原始问题相同的例外,因为它无法识别"Provider"键,而OleDbConnection将为您提供“无法识别的数据库格式”。任何一种连接类型都是错误的。

无论您使用的是SQL Server还是Access数据库-看来您的应用程序都连接到这两个数据库-您需要确保为该数据库使用正确的连接类型和连接字符串。

现在让我们深入探讨其他一些问题:


SQL注入

不要连接字符串以构造SQL。

请务必阅读Little Bobby Tables。避免SQL注入不应该是事后的想法。从一开始就保护您的应用程序。这样做的方法是参数化您的查询。

暂时忽略

此确切

查询的危险,这是您应该执行的操作:

SqlCommand cmd = new SqlCommand("SELECT User_Password FROM Registration WHERE Email = @Email"); // ^^^^^^ parameter cmd.Parameters.Add(new SqlParameter { Name = "@Email", SqlDbType = SqlDbType.NVarChar, Size = 100, // or whatever length your Email column is. Value = txtEmail.Text // ^^^^^^^^^^^^^ paramter's value }); 您可以使用其他Add重载,但我更喜欢此重载,因为它很清楚您正在设置哪些属性与许多其他重载。我见过人们使用错误的“数据库类型”并获得运行时错误,而不是编译错误,例如当他们使用Oracle或MySql时传递一个SqlDbType值,并且它默默地将该值作为object value参数传递。您会在SO的许多答案中遇到这些过载的示例。

您还将看到AddWithValue经常使用-

don't use it。至少对于SQL Server而言,这比它值得的麻烦更多。

密码恢复这就是我所说的确切查询的危险...

从不以纯文本格式存储密码。

您永远不要向他人发送密码,因为您永远都无法检索它。相反,您的数据库应包含密码的哈希。您的User_Password列不仅对人眼而且对于用于检索它的任何系统都应该看起来像垃圾。

“密码恢复”是一个不正确的名词,如果您做对的话。处理忘记密码的现代实践实际上是“访问恢复”,并且通常涉及短暂的令牌,这些令牌使您可以提供新密码。

密码哈希和访问恢复过程之类的话题已得到充分记录,因此我不再赘述。
© www.soinside.com 2019 - 2024. All rights reserved.