-1

So i'm writing a program with C# and Sql, i created a database in visual studio and DataSet, and connected it to DataGridView. But the problem is, when i insert something into DataGridView row, all strings are presented as question marks, but with "int" type everything is okay.

enter image description here

    namespace MH
{
    public partial class PatientForm : Form
    {
        SqlConnection conn = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Admin\source\repos\MH\MH\MH.mdf;Integrated Security=True");
        public PatientForm()
        {
            InitializeComponent();
        }

        void populate()
        {
            conn.Open();
            string query = "select * from Patient";
            SqlDataAdapter da = new SqlDataAdapter(query, conn);
            SqlCommandBuilder builder = new SqlCommandBuilder(da);
            var ds = new DataSet();
            da.Fill(ds);
            PatientGV.DataSource = ds.Tables[0];
            conn.Close();

        }

        private void label9_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void PatientForm_Load(object sender, EventArgs e)
        {
            populate();
            PatientGV.Columns[0].HeaderText = "ID пациента";
            PatientGV.Columns[1].HeaderText = "Имя";
            PatientGV.Columns[2].HeaderText = "Адрес";
            PatientGV.Columns[3].HeaderText = "Телефон";
            PatientGV.Columns[4].HeaderText = "Возраст";
            PatientGV.Columns[5].HeaderText = "Пол";
            PatientGV.Columns[6].HeaderText = "Группа крови";
            PatientGV.Columns[7].HeaderText = "Основная болезнь";
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Home h = new Home();
            h.Show();
            this.Hide();
        }

        
        private void button2_Click(object sender, EventArgs e)
        {
            conn.Open();
            string query = "update Patient set PatName = '" + PatName.Text + "', PatAddress = '" + PatAd.Text + "', PatPhone = '" + PatPhone.Text + "', PatAge = '" + PatAge.Text + "', PatGender = '" + GenderCb.SelectedItem.ToString() + "', PatBlood = '" + BloodCb.SelectedItem.ToString() + "', PatDisease = '" + MajorTb.Text + "'  where PatId = '" + PatId.Text + "'";
            SqlCommand cmd = new SqlCommand(query, conn);
            cmd.ExecuteNonQuery();
            MessageBox.Show("Пациент успешно обновлен");
            conn.Close();
            populate();
        }

        private void PatientGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                DataGridViewRow row = this.PatientGV.Rows[e.RowIndex];
                PatId.Text = row.Cells[0].Value.ToString();
                PatName.Text = row.Cells[1].Value.ToString();
                PatAd.Text = row.Cells[2].Value.ToString();
                PatPhone.Text = row.Cells[3].Value.ToString();
                PatAge.Text = row.Cells[4].Value.ToString();
                MajorTb.Text = row.Cells[7].Value.ToString();
            }
        }



        private void button1_Click(object sender, EventArgs e)
        {
            if (PatId.Text == "" || PatName.Text == "" || PatAd.Text == "" || PatPhone.Text == "" || PatAge.Text == "" || MajorTb.Text == "")
                MessageBox.Show("Пустые поля не принимаются!");
            else
            {
                conn.Open();
                string query = "insert into Patient values(" + PatId.Text + ",'" + PatName.Text + "','" + PatAd.Text + "','" + PatPhone.Text + "'," + PatAge.Text + "," +
                    "'" + GenderCb.SelectedItem.ToString() + "','" + BloodCb.SelectedItem.ToString() + "','" + MajorTb.Text + "')";
                SqlCommand cmd = new SqlCommand(query, conn);
                cmd.ExecuteNonQuery();
                MessageBox.Show("Запись успешно добавлена!");
                conn.Close();
                populate();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (PatId.Text == "")
                MessageBox.Show("Введите ID пациента");
            else
            {
                conn.Open();
                string query = "delete from Patient where PatId=" + PatId.Text + "";
                SqlCommand cmd = new SqlCommand(query, conn);
                cmd.ExecuteNonQuery();
                MessageBox.Show("Пациент успешно удален");
                conn.Close();
                populate();
            }
        }
    }
}

I'll be glad to any help! Edit: added code of the form for clarification

Carl
  • 345
  • 5
  • 23
  • you're right, it's nvarchar, and is selected from combobox, so i'm not sure what's the problem.. – Carl Jun 10 '21 at 17:33
  • and the thing is, when i insert into directly in database, it looks just fine, so i guess the problem is somewhere in datagridview – Carl Jun 10 '21 at 17:34
  • 2
    I would guess you treated the values as a `varchar` when you inserted the data, and thus now they are `?` characters for characters that weren't in the code page. – Thom A Jun 10 '21 at 17:40
  • so i edited the code into the original post, but how could i check the data returned from the DB? i mean, i checked the data in db that i inserted from the form, and it's the same question marks, but when i insert the data into the DB itself, everything is okay – Carl Jun 10 '21 at 17:51
  • `"delete from Patient where PatId=" + PatId.Text + ""` - please start with https://stackoverflow.com/q/332365/11683 before you proceed. This will also solve [your problem](https://stackoverflow.com/a/53909729/11683) as a side effect. Then please look into removing the form-level connection object, and into replacing all the `Open` and `Close` calls with `using`. – GSerg Jun 10 '21 at 17:52
  • *"I would guess you treated the values as a `varchar` when you inserted the data"* and we have a winner. **parametrise** your statements. It's no good defining a column as an `nvarchar` if you're going to **insecurely** inject `varchar` values. – Thom A Jun 10 '21 at 17:56
  • yes, but fields in my database are in russian, so wouldn't it be more logical to use nvarchar for them? – Carl Jun 10 '21 at 18:19
  • It would be, but instead you are using `varchar` in all your queries that [insecurely](https://stackoverflow.com/q/332365/11683) inject the values. – GSerg Jun 10 '21 at 18:23
  • *"how could i check the data returned from the DB?"* You could set a breakpoint after `da.Fill(ds)` and then examine the value of `ds.Tables[0].Rows[0].Field(1)` in the immediate window. – Rufus L Jun 10 '21 at 18:28
  • @GSerg i'm sorry, i've read the post about injecting values, but i couldn't figure it out..should i get rid of ' quotes, or it isn't the problem? – Carl Jun 10 '21 at 18:42
  • Don't manually inject string data (or any other kind of data) into your query. Use [SqlParameters](https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlparameter) to provide values and the framework will take care of converting to the correct data types, quoting strings and (important in this case) sending `nvarchar` values instead of `varchar`. – AlwaysLearning Jun 10 '21 at 23:42

1 Answers1

1

You can try the following steps to solve the problem about question marks in the datagirdview.

First, you could create the following table in your database.

CREATE TABLE [dbo].[Patient] (
    [Id]      INT           NOT NULL,
    [Name]    NVARCHAR (50) NOT NULL,
    [Age]     INT           NOT NULL,
    [Address] NVARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)
);

Second, Please try the following code to use SqlParameters to insert data to database.

  SqlConnection conn = new SqlConnection(@"CONNSTR");
        void populate()
        {
            conn.Open();
            string query = "select * from Patient";
            SqlDataAdapter da = new SqlDataAdapter(query, conn);
            SqlCommandBuilder builder = new SqlCommandBuilder(da);
            var ds = new DataSet();
            da.Fill(ds);
            dataGridView1.DataSource = ds.Tables[0];
            conn.Close();

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            populate();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (txtId.Text == "" || txtName.Text == "" || txtAge.Text == "" || txtAddress.Text == "" )
                MessageBox.Show("Пустые поля не принимаются!");
            else
            {
                conn.Open();
                string query = "insert into Patient(Id,Name,Age,Address)values(@Id,@Name,@Age,@Address)";
                SqlCommand cmd = new SqlCommand(query, conn);
                cmd.Parameters.AddWithValue("@Id",Convert.ToInt32(txtId.Text));
                cmd.Parameters.AddWithValue("@Name", txtName.Text);
                cmd.Parameters.AddWithValue("@Age", Convert.ToInt32(txtAge.Text));
                cmd.Parameters.AddWithValue("@Address", txtAddress.Text);

                cmd.ExecuteNonQuery();
                MessageBox.Show("Запись успешно добавлена!");
                conn.Close();
                populate();
            }
        }

Result:

enter image description here

Jack J Jun
  • 5,633
  • 1
  • 9
  • 27
  • https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/ – GSerg Jun 11 '21 at 07:04