Ключевое слово не поддерживается: 'поставщик' при попытке открыть соединение SQL - PullRequest
0 голосов
/ 16 июня 2020

Я новичок в C# и SQL, поэтому буду очень признателен за вашу помощь и советы.

Моя идея состоит в том, чтобы подключиться к DB с помощью SQL, выберите пароль и адрес электронной почты и отправьте его человеку, который хочет восстановить пароль учетной записи, по электронной почте (соединение SMTP ).

Моя проблема что я пытаюсь восстановить пароль для моего проекта C# через SQL, но получаю следующую ошибку : «Ключевое слово не поддерживается: '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("abcd@gmail.com");
                    // 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("abcd@gmail.com", "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();
        }
    }
}

1 Ответ

0 голосов
/ 17 июня 2020

У вас есть пять (5!) Строк подключения в теле вашего сообщения. Единственный, который вы используете, - это тот, который жестко закодирован в классе frmRecoveryPassword как поле cs.

SqlConnection жаловался, потому что он не распознает хотя бы одно имя / пары значений. Это потому, что это строка подключения для OLEDB, а не SQL Server.

Судя по тому, что вы опубликовали, похоже, что вы пытались подключиться к базе данных Access. Для этого вам нужно будет использовать OleDbConnection. Однако, судя по комментариям, это не так. Вы действительно хотите подключиться к базе данных SQL сервера, поэтому 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 серверные базы данных.

Тот, что на скриншоте (из комментариев), неверен. Это гибрид: вы указали поставщика OleDb (для доступа) и файл базы данных сервера SQL. Похоже, вы скопировали путь к файлу .mdf из первой строки подключения в app.config и использовали его во второй строке, где находился файл .accdb. SqlConnection даст вам то же исключение, что и исходный вопрос, потому что он не распознает ключ "Provider", а OleDbConnection даст вам «нераспознанный формат базы данных». Это неверно для любого типа подключения.

Используете ли вы SQL серверную базу данных или базу данных 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 перегрузки, которые вы можете использовать, но я предпочитаю эту из-за того, насколько ясно, какие свойства вы устанавливаете по сравнению со многими другими перегрузками. Я видел, как люди использовали неправильный «Тип БД» и получали ошибки времени выполнения вместо ошибок компиляции, например, передавая значение SqlDbType, когда они использовали Oracle или MySql, и он молча передает это значение как object value параметр. Вы встретите примеры этих перегрузок во многих ответах на SO.

Вы также увидите AddWithValue много используется - не используйте . Это больше проблем, чем того стоит, по крайней мере, с SQL Сервером.

Восстановление пароля

Это то, что я имел в виду под опасностью этого точного запроса ...

Никогда не храните пароли в виде обычного текста.

Вы никогда не должны отправлять кому-либо свой пароль, потому что вы никогда не сможете его восстановить . Вместо этого ваша база данных должна содержать ha sh пароля. Столбец User_Password должен выглядеть мусором не только для человеческого глаза, но и для любой системы, используемой для его извлечения.

«Восстановление пароля» - неточный термин, если вы все делаете правильно. Современные методы работы с забытыми паролями - это на самом деле «восстановление доступа», и они обычно включают недолговечные токены, которые позволяют вам указать новый пароль.

Такие темы, как хеширование паролей и процедуры восстановления доступа, хорошо задокументированы, поэтому я выиграл 't go в них дальше.

...