Обновление сетки данных с сервера SQL - процесс обновления не работает

У меня есть SQL-сервер, и я хочу показать его в основной форме моего приложения. Я следовал некоторым руководствам, и мне удалось установить связь между dataGrid и таблицей SQL-сервера.

Проблема в том, что когда я хочу обновить сетку данных и снова синхронизировать/перезагрузить таблицу с SQL-сервера.

У меня есть обработчик событий, который вызывает функцию updateDatadrid() каждый раз, когда я добавляю/редактирую строки в базе данных.

Когда я впервые запускаю приложение, я вызываю эту функцию, и она работает, но после этого, если я снова вызываю ее с этим обработчиком, я получаю некоторые ошибки.

Недопустимая межпоточная операция: доступ к элементу управления '' получен из потока, отличного от потока, в котором он был создан.

Вне функции (глобальные переменные):

SqlConnection sConDataGrid; 
DataSet dbDataSet;
SqlDataAdapter da;
BindingSource dbBind;
string sqlCommand;

EDIT - I forgot to add :
DataGridView _dbView;

Это мой код:

private void updateDataGrid()
{
        using (sConDataGrid = new SqlConnection("Data Source=" + SettingsForm.getAddress + ";Initial Catalog=" + SettingsForm.getDatabase + ";Integrated Security=False;User Id=" + SettingsForm.getUser + ";Password=" + SettingsForm.getPassword + ";Connect Timeout=0;"))
        {
            sConDataGrid.Open();
            sqlCommand = "select top 200 * FROM cstPackages order by _dateTime desc"; //reading the db from end to start   
            using (da = new SqlDataAdapter(sqlCommand, sConDataGrid))
            {
                da.Fill(dbDataSet, "cstPackages");
                    dbBind = new BindingSource(dbDataSet, "cstPackages");
                    _dbView.DataSource = dbBind;
                sConDataGrid.Close();
            }
        }
}

Я пытался поиграть с этим, вызывая только функцию da.Fill() после первого вызова этой функции, но она не обновляла сетку данных. Я попытался очистить набор данных перед тем, как заполнить его снова, но это привело к сбою программы. Я пытался просто сделать _dbView.Refresh(), но это тоже не сработало..

РЕДАКТИРОВАТЬ Я не понимаю, почему если я делаю кнопку, и ставлю обработчик события "щелчок", и я вызываю свою функцию из этого обработчика события - она ​​работает! И если я вызываю эту функцию из обработчика событий SerialPort dataReceived - я получаю эту ошибку! в чем разница? Я подумал, может быть, я создал обработчик событий не так, поэтому я просто перетащил элемент управления SerialPort из дизайнера и дважды щелкнул по событию, произошло то же самое.

Я пытался сделать таймер, включить его и в конце функции вызвать его на stop(), а в полученном сериале установить его на start(), но все, что я делаю в обработчике SerialPort, как бы "вне" программы. Не запускает таймер.


person Itay    schedule 26.12.2012    source источник
comment
Я предполагаю, что _dbView - это ваш DataGrid. Это правильно? Вы пробовали _dbView.DataBind() после строки, в которой вы установили DataSource?   -  person Melanie    schedule 27.12.2012
comment
@Melanie - Да, это мой DatGrid, и я не пробовал это раньше, но я не проверял, и такой функции нет :/   -  person Itay    schedule 27.12.2012
comment
Недопустимая межпоточная операция: доступ к элементу управления '' получен из потока, отличного от потока, в котором он был создан. Какой элемент управления и где возникает эта ошибка? Похоже, вы пытаетесь получить доступ к чему-то из другого потока, чем то, что было создано. Вероятно, dataGridView. Решение может состоять в том, чтобы получить к нему доступ через Invoke, но не может сказать вам больше, если вы не предоставите более подробную информацию об ошибке.   -  person a''    schedule 27.12.2012
comment
Когда возникает эта ошибка, я получаю эту ошибку с ' '. Отладчик указывает на code _dbView.DataSource = dbBind; code строка. У меня есть полученный обработчик событий, подключенный к COM-порту, и когда я получаю данные на COM-порт, я добавляю/изменяю базу данных в соответствии со строкой, а затем снова вызываю эту функцию.   -  person Itay    schedule 27.12.2012
comment
Я думаю, проблема в том, что вы создали свой DataGrid в своем основном потоке. Но поток обработки событий, который запускается в ответ на событие COM-порта, пытается изменить графический интерфейс. Возможно, поток обработки событий может отправить сообщение в основной поток, чтобы обновить DataGrid.   -  person Steve Wellens    schedule 27.12.2012
comment
Хорошо, это звучит логично, но у меня нет опыта работы с потоками. Я даже не создал ни одного потока самостоятельно, все эти потоки, вероятно, являются побочным эффектом моего программирования. Как я могу передавать данные между потоками? Я вызываю эту функцию из четного обработчика, и она выполняется в своем потоке:/   -  person Itay    schedule 27.12.2012
comment
Я погуглил и нашел это: msdn.microsoft.com /en-us/library/ms171728(v=vs.80).aspx Как сделать потокобезопасные вызовы к элементам управления Windows Forms Мне сказали, что я должен использовать BackgroundWorker — так я и сделал. Я создал BackgroundWorker и в полученном обработчике COM я вызвал BackgroundWorker.RunWorkerAsync(), а из события RunWorkerCompleted я вызвал свою функцию, но это не помогло. то же самое произошло здесь...   -  person Itay    schedule 27.12.2012
comment
Пожалуйста, ознакомьтесь с часто задаваемыми вопросами, чтобы узнать, как обстоят дела с переполнением стека. Если у вас есть ответ, опубликуйте его как ответ, не редактируйте его в своем вопросе. Затем, когда сможете, отметьте его как ответ, который сработал для вас, щелкнув галочку рядом с ним. Вот как мы знаем, какие ответы решены.   -  person Damien_The_Unbeliever    schedule 27.12.2012


Ответы (3)


РЕШЕНО После прочтения этого: http://msdn.microsoft.com/en-us/library/ms171728%28VS.80%29.aspx Я попытался использовать Invokes, и это сработало!

new code:
        delegate void SetDataGridCallback();

        private void updateDataGrid()
        {
            if (this._dbView.InvokeRequired)
            {
                SetDataGridCallback d = new SetDataGridCallback(updateDataGrid);
                this.Invoke(d, new object[] {  });
            }
            else
            {
                using (sCon2 = new SqlConnection("Data Source=" + SettingsForm.getAddress + ";Initial Catalog=" + SettingsForm.getDatabase + ";Integrated Security=False;User Id=" + SettingsForm.getUser + ";Password=" + SettingsForm.getPassword + ";Connect Timeout=0;"))
                {
                    sCon2.Open();
                    string sqlCommand = "select top 200 * FROM cstPackages order by _dateTime desc"; //reading the db from end to start   
                    using (da = new SqlDataAdapter(sqlCommand, sCon2))
                    {
                        dbDataSet.Clear();
                        da.Fill(dbDataSet, "cstPackages");
                        BindingSource dbBind = new BindingSource(dbDataSet, "cstPackages");
                        _dbView.DataSource = dbBind;
                        _dbView.Refresh();
                         sCon2.Close();
                    }
                }
            }
        }
person Itay    schedule 27.12.2012

Попробуй это :

     private void fill_grid()
    {

        SqlCommand cmd = new SqlCommand();
        cmd.CommandText = "Your sql command ";

        cmd.Parameters.Add("@param", SqlDbType.VarChar).Value = your_control.Text;

        cmd.CommandType = CommandType.Text;
        cmd.Connection = this.sqlConnection1;
        this.sqlConnection1.Open();


        SqlDataAdapter adpt = new SqlDataAdapter(cmd);
        DataSet ds = new DataSet();
        adpt.Fill(ds);


        your_grid.DataSource = ds;


        this.sqlConnection1.Close();

        this.your_grid.DataBind();



    }

Затем все, что вам нужно сделать, это вызывать этот метод всякий раз, когда вам нужно «обновить» сетку.

person briskovich    schedule 27.12.2012
comment
Эй, я не могу использовать .DataBind(); . Он не показывает эту функцию, и если я напишу ее вручную - я получаю ошибку компиляции. - person Itay; 27.12.2012
comment
msdn.microsoft.com /en-us/library/ Нет такого метода DataBind() - person Itay; 27.12.2012
comment
Вы должны добавить эти две ссылки на сборки в свое решение System.Data и System.Data.SqlClient. Тогда оно будет работать. - person briskovich; 27.12.2012

Думаю много причин. один: ваш кеш не очищен два: ваш компьютер работает медленно thd: ваше обновление на самом деле не является обновлением. четыре: может быть, у него задержка по времени

сначала вы делаете свой «выбор sql» в базе данных, убедитесь, что вы действительно совершаете два, вы можете написать фоновое слово, чтобы обновить время вашей программы. или сделать кнопку для обновления. thd заставит вашу работу снова открыться.

person wangliuzheng    schedule 27.12.2012
comment
Я ждал несколько минут, надеясь, что он обновится, но этого не произошло. База данных сейчас редко обновляется (в моих тестах), я могу контролировать частоту данных COM-порта. Я хочу отменить фоновое обновление каждые x секунд, потому что я думаю, что это пустая трата ресурсов. Я точно знаю, когда БД была изменена, поэтому я точно знаю, когда обновлять DataGrid. - person Itay; 27.12.2012