Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Глупый вопрос по работе с БД (DataGridView) 
:(
    Опции темы
brother79
Дата 4.10.2010, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Здравствуйте. 

На текущем этапе нужен простой вар-нт редактирования таблицы. Я использую DataGridView

Нашёл где-то такой код:

Код

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                this.Validate();
                this.algorithmBindingSource.EndEdit();
                this.algorithmTableAdapter.Update(this.diagramDataSet.algorithm);
                //MessageBox.Show("Update successful");
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Update failed");
            }
        }



Принципе работает, с некоторыми неточностями. Когда сохраняется последняя строка таблицы, которая новая - то при первом сохранении - сохраняется нормально, автоматически расчитывается id как автоинкремент, но в самой таблице в компоненте - id никак не обновляется и при повторном сохранении этой строки - срабатывает исключение.

Как правильно сделать это простое сохранение результатов?


--------------------
PM MAIL WWW   Вверх
brother79
Дата 4.10.2010, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Что-то порылся порылся очень даже не глупый вопрос получается :( Ghtдлагают делать через хранимую процедуру своё добавление с возвратом параметра. А других вар-ов нету?


--------------------
PM MAIL WWW   Вверх
jonie
Дата 4.10.2010, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



без хранимки можно, просто используя два sql statement для выполнения. Подробнее: http://msdn.microsoft.com/en-us/library/ks9f57t0.aspx


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
brother79
Дата 5.10.2010, 06:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Почитал, можно select добавить после insert только в этом дураском TableAdapter не могу найти куда свой запрос на добавление засунуть. И вообзе компоненту sqlDataAdapter не вижу, которая в доке описана.


--------------------
PM MAIL WWW   Вверх
jonie
Дата 5.10.2010, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



В общем я тут поразмыслил и сделал следующую штуку.
1) я унаследовался от TableAdapter-а, который использовал назвав класс TblTableAdapter2, чтобы можно было override-днуть методы
Код

public override int Update(global::System.Data.DataRow[] dataRows)
и
public override int Insert(string p1)


Собственно посмотрев в код, можно убедиться что если вызывать AcceptChanges, то будет вызван первый (в отличие от ручного добавления)... возможно надо будет переопределить и другие методы (не смотрел) которые инсертят данные (на первый взгляд таковых более нет).

2) я сделал метод у адаптера в DataSet-е который получает последний вставленный Id-шник по sql запросу select @@IDENTITY (см. примечание2)

3) в перегруженном методе Update у себя я произвожу обновления по одной строке ,статус которой равен Added, после чего руками меняю её Id шник и снова сбрасываю ее состояние на Unchanged вызывая AccepChanges().

4) а да, в коде сгененым дизайнером я подменил название класса Адаптера на мой унаследованный руками (в дальнейшем визуальный редактор не будет это ломать).

Пример в аттачменте...


Примечания:
2) В примере я использовал SQLCe в котором обычно нет конкуренции при вставках данных. Однако, для MSSQLя не уверен что базовый Update у адаптера не производит соединение\отсоединение Connection от источника данных, это надо проверить, если не производит тогда хорошо - у нас есть сессия, в рамках которой можно использовать SCOPE_IDENTITY(). . это надо проверить например тем же профилировщиком для MSSQL....

Да, наверно можно открыть пееред base.Update-тами соединение, и использовать метод Insert() , т.к. он не закрывает-открывает соединение, если оно уже открыто:
Код

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
        [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")]
        [global::System.ComponentModel.DataObjectMethodAttribute(global::System.ComponentModel.DataObjectMethodType.Insert, true)]
        public virtual int Insert(string p1) {
            if ((p1 == null)) {
                this.Adapter.InsertCommand.Parameters[0].Value = global::System.DBNull.Value;
            }
            else {
                this.Adapter.InsertCommand.Parameters[0].Value = ((string)(p1));
            }
            global::System.Data.ConnectionState previousConnectionState = this.Adapter.InsertCommand.Connection.State;
            if (((this.Adapter.InsertCommand.Connection.State & global::System.Data.ConnectionState.Open) 
                        != global::System.Data.ConnectionState.Open)) {
                this.Adapter.InsertCommand.Connection.Open();
            }
            try {
                int returnValue = this.Adapter.InsertCommand.ExecuteNonQuery();
                return returnValue;
            }
            finally {
                if ((previousConnectionState == global::System.Data.ConnectionState.Closed)) {
                    this.Adapter.InsertCommand.Connection.Close();
                }
            }
        }


Это сообщение отредактировал(а) jonie - 5.10.2010, 11:21

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  w7.rar 39,94 Kb


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
umlprog
Дата 7.10.2010, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 5.12.2009

Репутация: нет
Всего: нет



Цитата(jonie @ 5.10.2010,  11:17)
В общем я тут поразмыслил и сделал следующую штуку.
1) я унаследовался от TableAdapter-а, который использовал назвав класс TblTableAdapter2, чтобы можно было override-днуть методы
Код

public override int Update(global::System.Data.DataRow[] dataRows)
и
public override int Insert(string p1)


Собственно посмотрев в код, можно убедиться что если вызывать AcceptChanges, то будет вызван первый (в отличие от ручного добавления)... возможно надо будет переопределить и другие методы (не смотрел) которые инсертят данные (на первый взгляд таковых более нет).

2) я сделал метод у адаптера в DataSet-е который получает последний вставленный Id-шник по sql запросу select @@IDENTITY (см. примечание2)

3) в перегруженном методе Update у себя я произвожу обновления по одной строке ,статус которой равен Added, после чего руками меняю её Id шник и снова сбрасываю ее состояние на Unchanged вызывая AccepChanges().

4) а да, в коде сгененым дизайнером я подменил название класса Адаптера на мой унаследованный руками (в дальнейшем визуальный редактор не будет это ломать).


А просто перезаполнить свой грид после апдейта не пробовали?  smile 
PM MAIL   Вверх
jonie
Дата 7.10.2010, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 22
Всего: 118



umlprog, это не нормальный подход, "школьный" ....


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
brother79
Дата 12.10.2010, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Что-то я запарился уже с этими таблицами.
С наследованием - что-то не разобрался пока, я делаю на wpf  -  там немного отличается похоже. а так просто - сделал запрос в датасете чтобы последнюю добавленную дёргать как в примере - но он не дёргает никак. Я уже сделал запрос на добавление отдельный, подряд сначала добавление вызываю, потом хочу последний дёрнуть - он пустоту возвращает и всё.


--------------------
PM MAIL WWW   Вверх
brother79
Дата 12.10.2010, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Дошёл до такого кода:

Код

   public override int Update(diagramDataSet.section1DataTable dataTable)
        {
            int rv = 0;

            System.Data.DataTable t = dataTable.GetChanges();
            if (t != null)
            {
                foreach (WpfApplication1.diagramDataSet.section1Row addedRow in t.Rows)
                {
                    if (addedRow.id < 0)
                    {
                        rv += base.Update(addedRow);
                        //refresh our Row ...
                        try
                        {
                            t.Columns[2].ReadOnly = false;
                            diagramDataSet.section1DataTable tt = this.GetDataByLast();
                            if (tt.Rows.Count > 0)
                            {
                                WpfApplication1.diagramDataSet.section1Row r = tt.Rows[0] as WpfApplication1.diagramDataSet.section1Row;
                                long lastId = r.id;
                                addedRow.id = lastId;
                                addedRow.AcceptChanges();
                            }
                        }
                        finally
                        {
                            t.Columns[2].ReadOnly = true;
                        }
                    }
                }
                dataTable.Merge(t);
            }
            rv += base.Update(dataTable);
            return rv;
        }


1) не могу получить никак последний id, запрос пустой получается
2) Когда делаю мерге - у меня добавляется строка, вместо того, чтобы поменять id, т.е. не правильный подход

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  2.rar 184,45 Kb


--------------------
PM MAIL WWW   Вверх
brother79
Дата 12.10.2010, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Сделал так:

Код


        public override int Update(diagramDataSet.section1DataTable dataTable)
        {
            int rv = 0;

            System.Data.DataTable t = dataTable.GetChanges();
            if (t != null)
            {
                foreach (WpfApplication1.diagramDataSet.section1Row addedRow in t.Rows)
                {
                    if (addedRow.RowState == System.Data.DataRowState.Added)
                    {
                        int colIndex = dataTable.Columns.IndexOf("id");
                        rv += base.Update(addedRow);
                        //refresh our Row ...
                        try
                        {
                            WpfApplication1.diagramDataSet.section1Row r = dataTable.Rows.Find(addedRow.id) as WpfApplication1.diagramDataSet.section1Row;
                            dataTable.Columns[colIndex].ReadOnly = false;
                            r.id = System.Convert.ToInt64(this.MaxId());
                            addedRow.AcceptChanges();
                        }
                        finally
                        {
                            dataTable.Columns[colIndex].ReadOnly = true;
                        }
                    }
                }
                //dataTable.Merge(t);
            }
            rv += base.Update(dataTable);
            return rv;
        }



Теоретически работает, только не нравится костыль с вычислением добавленного id, который просто получается как max(id). Так я это и не смог победить


--------------------
PM MAIL WWW   Вверх
brother79
Дата 13.10.2010, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Если я руками добавляю эл-нт, типа: 

Код


                diagramDataSet.section1Row r = this.diagramDataSet.section1.NewRow() as diagramDataSet.section1Row;
                r.name = nameTextBox.Text.ToString();
                r.description = descriptionTextBox.Text.ToString();
                this.diagramDataSet.section1.Rows.Add( r );
// Вот до сюда - всё нормально, дальше надо в гриде перевести строку на новую запись, как это сделать?

                Int64 id = r.id;

                int i = diagramDataSet.section1.Rows.IndexOf( r );

// т.е. надо как-то посчитать i чтобы потом сделать:

                section1ViewSource.View.MoveCurrentToPosition(i);

// Сейчас i встаёт на последнюю строку, т.к. в DataGrid - таблица может быть сортированна, нужно перемещаться не на последнюю, а на добавленную, которая встаёт где-то в середине.



Как вычислить позицию для System.Windows.Data.CollectionViewSource ?


--------------------
PM MAIL WWW   Вверх
brother79
Дата 13.10.2010, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: нет
Всего: 6



Sory, поторопился с выводами

Это сообщение отредактировал(а) brother79 - 13.10.2010, 12:02


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0868 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.