powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / c#, транзакция в FBDataAdapter.Update()
17 сообщений из 17, страница 1 из 1
c#, транзакция в FBDataAdapter.Update()
    #39853286
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет.
Использую FirebirdSql.Data.FirebirdClient;
На внесение изменений в БД через FBDataAdapter у меня следующий код:

Код: c#
1.
2.
3.
4.
5.
6.
7.
FbTransaction txn = db.BeginTransaction();
da.UpdateCommand.Transaction = txn;
da.InsertCommand.Transaction = txn;
da.DeleteCommand.Transaction = txn;
da.SelectCommand.Transaction = txn; 
da.Update(dt); 
txn.Commit();


Ну в книжке так и написано, что для оборачивания в транзакцию обновления записей в таблице, в случае, если мы генерируем обновляющие запросы автоматом через CommandBuilder, надо перед update() присвоить транзакцию в select адаптера, т.к. он запрашивает метаданные таблицы.
Но у меня выскакивает null reference exception на строке da.UpdateCommand.Transaction = txn, как будто UpdateCommand пустая...
Тогда где и как запускать транзакцию? Я пока учусь, не ругайте)
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853398
Фотография pation
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aford,

Адаптерами уже никто не пользуется, смотри в сторону орм
а null reference exception, у тебя потому что ты не указал команду
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853645
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
pation, спасибо за совет про орм, обязательно обращу внимание, но сейчас главное в текущем разобраться)
Команду не указывал, она должна была сгенерироваться автоматом при инициализации
Код: c#
1.
2.
var cb = new FbCommandBuilder(da);
MessageBox.Show(cb.GetUpdateCommand.ToString());


Это все используется при открытии таблицы, а код в первом посте отрабатывает по нажатию на кн. сохранить.
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853687
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пардон, вот так надо:
Код: c#
1.
MessageBox.Show(cb.GetUpdateCommand().CommandText);


Как я понял, NullReferenceException было из-за того, что FbCommandBuilder был объявлен локально.
Теперь ошибка
"транзакция команды не была инициализирована"
System.InvalidOperationException: 'Execute requires the Command object to have a Transaction object when the Connection object assigned to the command is in a pending local transaction. The Transaction property of the Command has not been initialized.'

Хотя задаю вроде правильно
Код: c#
1.
2.
3.
4.
5.
6.
7.
FbTransaction txn = db.BeginTransaction();
MessageBox.Show(cb.GetUpdateCommand().CommandText); // тут ругается
da.UpdateCommand.Transaction = txn;
da.InsertCommand.Transaction = txn;
da.DeleteCommand.Transaction = txn;
da.Update(dt);
txn.Commit();


Если полностью убираю транзакцию
Код: c#
1.
2.
MessageBox.Show(cb.GetUpdateCommand().CommandText);
da.Update(dt);


то все работает и запрос обновления показывает без ошибки.
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853689
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aford, эм... и что в мессадж боксе? Есть небольшое ограничение, т.е. вариант когда упдейт команд не будет создан автоматически (не задан "первичный ключ" для дататейбл)...
Возьмите командбилдер - введите свой селект и посмотрите какие команды он вам нагенерит...
P.S.: вы сделайте сперва всё как написано в книжке...
P.P.S.: есть еще вариант c TransactionScope
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853694
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
buser, первичный ключ задан в ст. USER (есть еще 2 ограничения: запрос возвращает данные только из 1 таблицы и первичный ключ есть в резульатах запроса). В мессейджбоксе что-то вроде
авторUPDATE "TABLE" SET "USER" = @p1, "USER_NAME" = @p2 .. WHERE (("USER" = @p16))

Как раз по первичному ключу USER и строится логика обновления.
buser вы сделайте сперва всё как написано в книжке...
Я так и делаю :)
Пока не совсем понятно, как мне поможет здесь TransactionScope
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853709
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aford, а если показать весь код... от создания конекшна и дата адаптера?
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853715
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
buser,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
using System;
using System.Data;
using System.Windows.Forms;
using FirebirdSql.Data.FirebirdClient;

namespace FirebirdConnect
{
    public partial class Form1 : Form
    {        
        public FbConnection db;
        public FbDataAdapter da;
        public DataTable dt;
        public FbCommandBuilder cb;

        private void LoadGrid()
        {
            dt = new DataTable();           
            try
            {                                 
                da = new FbDataAdapter("select * from " + tbTableName.Text, db);                    
                cb = new FbCommandBuilder(da);                                                                                                     
                da.Fill(dt);                                    
                dataGridView1.DataSource = dt;                             
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }            
        }


        private void BtnConnect_Click(object sender, EventArgs e)
        {           
            FbConnectionStringBuilder fbConfig = new FbConnectionStringBuilder()
            {
                Charset = "WIN1251", // используемая кодировка
                UserID = "SYSDBA", // логин
                Password = "123456", // пароль
                Database = "path", // путь к файлу базы данных
                DataSource = "db.domain.ru", // адрес базы
                Port = 3051, // порт
                ServerType = FbServerType.Default 
            };                        
            var conStr = fbConfig.ToString();            
            db = new FbConnection(conStr);            
            db.Open();            
            LoadGrid();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            LoadGrid();
        }

        private void TsBtnUpdate_Click(object sender, EventArgs e)
        {
            //FbTransaction txn = db.BeginTransaction();                                                                                                                                                                                                                                 
            MessageBox.Show(cb.GetUpdateCommand().CommandText);                                                                                    
            //da.UpdateCommand.Transaction = txn;
            //da.InsertCommand.Transaction = txn;
            // da.DeleteCommand.Transaction = txn;                            
            //da.SelectCommand.Transaction = txn; 
            da.Update(dt); // передаем изменения                            
            //txn.Commit();        
        }
     }
}
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853757
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
pationaford,

Адаптерами уже никто не пользуется, смотри в сторону орм
а null reference exception, у тебя потому что ты не указал команду
Пользуются. ОРМ пользуются те, кто плохо знают возможности баз данных.

aford, открытие транзакций на клиенте - зло.
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853767
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
afordbuser,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
using System;
using System.Data;
using System.Windows.Forms;
using FirebirdSql.Data.FirebirdClient;

namespace FirebirdConnect
{
    ...
}


Все неправильно. Если используется подход через DataSet, то надо использовать типизированный DataSet
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853795
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Cat2, я ж DataSet-ом не пользуюсь, у меня одна таблица. Да и типизированный не за чем, если я обращаюсь к разным таблицам. Знаю, что датасеты со строгим контролем типов это хорошо в плане разработки, скорости и т.д., но сейчас меня интересует только почему не цепляется транзакция и вываливается исключение...
автороткрытие транзакций на клиенте - зло
Почему? Где их еще открывать? Если только писать сервер для клиента, который будет работать с БД и управлять с транзакциями?
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853919
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
afordCat2, я ж DataSet-ом не пользуюсь, у меня одна таблица. Да и типизированный не за чем, если я обращаюсь к разным таблицам. Знаю, что датасеты со строгим контролем типов это хорошо в плане разработки, скорости и т.д., но сейчас меня интересует только почему не цепляется транзакция и вываливается исключение...
автороткрытие транзакций на клиенте - зло
Почему? Где их еще открывать? Если только писать сервер для клиента, который будет работать с БД и управлять с транзакциями?


Если у Вас одна таблица, то Вы не умеете проектировать базы и понятия не имеете о нормализации.
Типизированный Dataset - модель базы данных, удобная для обращения к базе.

Да нафига Вам это цепляние ?
Единственный запрос и так выполняется в отдельной транзакции.

Когда нужно в единой транзакции выполнить несколько запросов - используются хранимые процедуры.

Зло в том, что если на клиенте открывается транзакция, то она должна быть и закрыта там же.
Пример. В транзакции два запроса на изменение.
Во время выполнения первого запроса клиент отвалился - террористы взорвали компьютер клиента. СУБД будет ждать "некоторое разумное время", что бы откатить эту операцию.
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39853976
Barkan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aford,

В коде не видно где создаются InsertrCommand, UpdateCommand, DeleteCommand.

Вот для примера мой код (правда это VB.NET + MS SQL, но это не принципиально, главное смотри на транзакцию и команды):

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
Public NotInheritable Class dbeCORE
   
   Private Sub New()
      'private constructor
   End Sub
   
   Private Shared strSQL As String = ""
   
   ''' <summary>
   ''' Возвращает таблицу стержней для указанного ТП
   ''' </summary>
   ''' <param name="TPR_ID">ИД ТП</param>
   ''' <returns>COR_ID, COR__TPR_ID, COR_NUMBER, COR_COLC, COR__MIX_ID, MIX_NAME, 
   ''' COR_MASSA, MIX_DENSITY, COR__MIX_IDR, MIX_NAMER, MIX_DENSITYR, COR_KIS, COR_GSS</returns>
   Public Shared Function SelectRows(ByVal TPR_ID As Integer) As DataTable
      strSQL = "select C.COR_ID, C.COR__TPR_ID, C.COR_NUMBER, C.COR_COLC, C.COR__MIX_ID, S1.MIX_NAME, " _
             & "C.COR_MASSA, S1.MIX_DENSITY, C.COR__MIX_IDR, S2.MIX_NAME as MIX_NAMER, S2.MIX_DENSITY as MIX_DENSITYR, " _
             & "C.COR_KIS, C.COR_GSS " _
             & "from CORE as C " _
             & "join SANDMIX as S1 on C.COR__MIX_ID=S1.MIX_ID " _
             & "left join SANDMIX as S2 on C.COR__MIX_IDR=S2.MIX_ID " _
             & "where C.COR__TPR_ID=<TPR_ID> order by C.COR_NUMBER"
      strSQL = strSQL.Replace("<TPR_ID>", TPR_ID.ToString())
      Return DBExecutor.ExecuteSelectCommand(strSQL)
   End Function
   
   Public Shared Sub UpdateRows(ByVal DT As DataTable, ByVal TR As SqlTransaction)
      Dim AD As New SqlDataAdapter()
      strSQL = "insert into CORE (COR__TPR_ID, COR__MIX_ID, COR_NUMBER, COR_COLC, COR_MASSA, COR__MIX_IDR, COR_KIS, COR_GSS) " _
             & "values (@TPR_ID, @MIX_ID, @NUMBER, @COLC, @MASSA, @MIX_IDR, @KIS, @GSS)"
      AD.InsertCommand = New SqlCommand(strSQL, DBExecutor.CNN, TR)
      AD.InsertCommand.Parameters.Add("@TPR_ID", SqlDbType.Int, 10, "COR__TPR_ID")
      AD.InsertCommand.Parameters.Add("@MIX_ID", SqlDbType.Int, 10, "COR__MIX_ID")
      AD.InsertCommand.Parameters.Add("@NUMBER", SqlDbType.VarChar, 5, "COR_NUMBER")
      AD.InsertCommand.Parameters.Add("@COLC", SqlDbType.Decimal, 10, "COR_COLC")
      AD.InsertCommand.Parameters.Add("@MASSA", SqlDbType.Decimal, 10, "COR_MASSA")
      AD.InsertCommand.Parameters.Add("@MIX_IDR", SqlDbType.Int, 10, "COR__MIX_IDR")
      AD.InsertCommand.Parameters.Add("@KIS", SqlDbType.Decimal, 10, "COR_KIS")
      AD.InsertCommand.Parameters.Add("@GSS", SqlDbType.TinyInt, 10, "COR_GSS")
      strSQL = "update CORE set COR__TPR_ID=@TPR_ID, COR__MIX_ID=@MIX_ID, COR_NUMBER=@NUMBER, COR_COLC=@COLC, " _
             & "COR_MASSA=@MASSA, COR__MIX_IDR=@MIX_IDR, COR_KIS=@KIS, COR_GSS=@GSS " _
             & "where COR_ID=@COR_ID"
      AD.UpdateCommand = New SqlCommand(strSQL, DBExecutor.CNN, TR)
      AD.UpdateCommand.Parameters.Add("@TPR_ID", SqlDbType.Int, 10, "COR__TPR_ID")
      AD.UpdateCommand.Parameters.Add("@MIX_ID", SqlDbType.Int, 10, "COR__MIX_ID")
      AD.UpdateCommand.Parameters.Add("@NUMBER", SqlDbType.VarChar, 5, "COR_NUMBER")
      AD.UpdateCommand.Parameters.Add("@COLC", SqlDbType.Decimal, 10, "COR_COLC")
      AD.UpdateCommand.Parameters.Add("@MASSA", SqlDbType.Decimal, 10, "COR_MASSA")
      AD.UpdateCommand.Parameters.Add("@COR_ID", SqlDbType.Int, 10, "COR_ID")
      AD.UpdateCommand.Parameters.Add("@MIX_IDR", SqlDbType.Int, 10, "COR__MIX_IDR")
      AD.UpdateCommand.Parameters.Add("@KIS", SqlDbType.Decimal, 10, "COR_KIS")
      AD.UpdateCommand.Parameters.Add("@GSS", SqlDbType.TinyInt, 10, "COR_GSS")
      strSQL = "delete from CORE where COR_ID=@COR_ID"
      AD.DeleteCommand = New SqlCommand(strSQL, DBExecutor.CNN, TR)
      AD.DeleteCommand.Parameters.Add("@COR_ID", SqlDbType.Int, 10, "COR_ID")
      AD.Update(DT)
   End Sub
   
End Class
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39854006
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Cat2Если у Вас одна таблица, то Вы не умеете проектировать базы и понятия не имеете о нормализации.

Вопрос изначально стоял так "Почему не работает транзакция, почему выскакивает ошибка"
То, что я использую одну таблицу не значит, что я ничего не понимаю в проектировании и т.п., это все сугубо для примера и чтобы разобраться в текущем вопросе. Вот зачем делать такие выводы? Не понимаю.
Cat2Да нафига Вам это цепляние?

Я ж и говорю, разобраться, никакой цели кроме "Почему так не работает и как надо" я не преследую. Почему в книжке работает, а у меня нет? Компоненты доступа Firebird не работают или я делаю что-то не так? Книга Д. Сеппа, Microsoft ADO.NET. Только что там не firebird, а ole.
Стр. 390
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
string strConn, strSQL;
DataTabLe tbl = new DataTableC);
OleDbConnection en = new OleDbConnection(strConn);
OleDbDataAdapter da = new 01eDbDataAdapter(strSQL, Cn);
OleDbCommandBuilder cb = new QleDbCommandBuilder(da);
cn.Open();
da.Fill(tbl);
OleDbTransaction txn = cn.BeginTransaction();
da.Update(tbl);
txn.Commit();
cn.Close();


При вызове метода DataAdapterL'pdate объект CommandBuilder выбирает из БД
нужные метаданные, используя свойство SelectCommand объекта DataAdapter. Мы
не сопоставили объект Command в свойстве SelectCommand с только что созданной транзакцией. Следовательно, объекту CommandBuilder не удастся воспользоваться этим свойством, и он генерирует исключение.
Если добавить перед вызовом метода Update объекта DataAdapter такую строку, код успешно выполнится:
da.SelectCommand.Transaction = txn;


Cat2Единственный запрос и так выполняется в отдельной транзакции.

Транзакция в любом случае есть, хоть и не в явном виде.
Cat2Когда нужно в единой транзакции выполнить несколько запросов - используются хранимые процедуры.

Или пакетные запросы, но вопрос вначале все же был не об этом :)
Cat2Зло в том, что если на клиенте открывается транзакция, то она должна быть и закрыта там же.
Пример. В транзакции два запроса на изменение.
Во время выполнения первого запроса клиент отвалился - террористы взорвали компьютер клиента. СУБД будет ждать "некоторое разумное время", что бы откатить эту операцию.

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

Barkan, методы обновления создаются при инициализации коммандбилдера, а если еще точнее (по книжке), то в момент обновления он делает селект запрос в таблицу БД и на основании этого запроса генерирует логику обновления.
Без транзакции же все работает и я не прописываю все логику сам.
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #39854496
aford
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Разобрался.
Все, что нужно было сделать, это инициализировать новую команду на выборку данных, но уже с транзакцией (ну или сразу задавать транзакцию ей). То есть вместо
Код: c#
1.
2.
3.
4.
5.
6.
7.
FbTransaction txn = db.BeginTransaction();
da.UpdateCommand.Transaction = txn;
da.InsertCommand.Transaction = txn;
da.DeleteCommand.Transaction = txn;
da.SelectCommand.Transaction = txn; 
da.Update(dt); 
txn.Commit();


Надо было сделать так
Код: c#
1.
2.
3.
4.
FbTransaction txn = db.BeginTransaction();								  								
cb.DataAdapter.SelectCommand = new FbCommand("select * from users_test", db, txn);                                                                                                                                         
da.Update(dt);
txn.Commit();
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
c#, транзакция в FBDataAdapter.Update()
    #40060595
dsa0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aford,
Попробовал, как написали, запись не добавляется, ни ошибки, ничего.
Что я сделал не так?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
adaptFb.InsertCommand = new FirebirdSql.Data.FirebirdClient.FbCommand("Insert into  NOTICES(NOTICE, FDOC, FCOMMENT, WIN_USER, USER_NAME, DATE_REG) " +
                    "values (@NOTICE,@FDOC,@FCOMMENT,@WIN_USER,@USER_NAME,@DATE_REG", connFB, transFb);
cmdBilderFb = new FbCommandBuilder(adaptFb);
transFb = connFB.BeginTransaction();
adaptFb.InsertCommand.Parameters.Add("@NOTICE", notice);
adaptFb.InsertCommand.Parameters.Add("@FDOC", tbxDoc.Text);
adaptFb.InsertCommand.Parameters.Add("@FCOMMENT", tbxComment.Text);
adaptFb.InsertCommand.Parameters.Add("@WIN_USER", win_USER);
adaptFb.InsertCommand.Parameters.Add("@USER_NAME", userName);
adaptFb.InsertCommand.Parameters.Add("@DATE_REG", dtpCreate.Value.Date);
cmdBilderFb.DataAdapter.SelectCommand = new FirebirdSql.Data.FirebirdClient.FbCommand(strSelect, connFB, transFb);
adaptFb.Update(dTable);
transFb.Commit();
...
Рейтинг: 0 / 0
c#, транзакция в FBDataAdapter.Update()
    #40060723
dsa0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А, все, разобрался.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / c#, транзакция в FBDataAdapter.Update()
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]