powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / c#->SQLServer: Нет Exception при роллбэке в триггере
17 сообщений из 17, страница 1 из 1
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531654
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть вызов

Код: c#
1.
2.
3.
4.
strCmd = @"insert into [dbo].[logs](msg) values(@msg); select SCOPE_IDENTITY();";
// ...
object objid = cmd1.ExecuteScalar();
if (objid != DBNull.Value)



На инсерт есть триггер, который проверяет что-то и делает
Код: sql
1.
2.
3.
4.
5.
6.
7.
--...
IF @numrows>=1
BEGIN
	ROLLBACK TRAN;
	RAISERROR('Msg cannot be added', 16, 1);
	RETURN;
END



Этот триггер не генерирует Exception.
Каждый раз, даже когда триггер не добавляет запись и делает роллбек
здесь
object objid = cmd1.ExecuteScalar();

возвращается 2

Что не так?
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531674
BlackEric
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин,

А что вернет Select * from log?
Там мах id не 2?
SCOPE_IDENTITY (Transact-SQL) - это читали?
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531694
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlackEricРолг Хупин,

А что вернет Select * from log?
Там мах id не 2?
SCOPE_IDENTITY (Transact-SQL) - это читали?

нет, там не 2, а 258
читал, а толку? вопрос не в этом.
Если руками выполняю в ССМС тот же запрос, выловленный в профайлере получаю:

Код: sql
1.
2.
3.
4.
Msg 50000, Level 16, State 1, Procedure tr_дщп, Line 44 [Batch Start Line 15]
Msg cannot be added
Msg 3609, Level 16, State 1, Line 16
The transaction ended in the trigger. The batch has been aborted.



А в c# коде нет Exception и создается впечатление, что запрос отработал успешно.
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531728
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин, тело триггера покажите пож.
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531748
BlackEric
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я воспроизвел

Таблица:
Код: sql
1.
2.
3.
4.
5.
6.
Create Table logs
(
id int primary key identity(1,1),
msg nvarchar(MAX)
)
Go



Инсерты:
Код: sql
1.
2.
3.
4.
insert into logs(msg)values('qaz')
insert into logs(msg)values('qaz')
insert into logs(msg)values('edc')
insert into logs(msg)values('rfv')



Триггер:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE TRIGGER dbo.AI_CheckSingleRow
   ON  [dbo].[logs]
   AFTER INSERT, UPDATE
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

    -- Insert statements for trigger here
	DECLARE @numrows int;
	SET @numrows = 0;

	Select @numrows = count(*) from inserted 

	IF @numrows > 1
	BEGIN
		ROLLBACK TRAN;
		RAISERROR('Msg cannot be added', 16, 1);
		RETURN;
	END

END
GO



Запрос падающий из студии:
Код: sql
1.
2.
3.
4.
5.
Update logs
Set msg = '123'
where msg = 'qaz'
Go
Select SCOPE_IDENTITY()



Оно же из шарпа нормально отрабатывает (не падает):
Код: 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.
static void Main(string[] args)
        {
            string connectionString = "Data Sou...";

            SqlDataReader rdr = null;
            SqlConnection con = null;
            SqlCommand cmd = null;

            try
            {
                con = new SqlConnection(connectionString);
                con.Open();

                string commandText = "Select SERVERPROPERTY('productversion'), @@servername";

                cmd = new SqlCommand(commandText);
                cmd.Connection = con;

                rdr = cmd.ExecuteReader();

                while (rdr.Read())
                {
                    Console.WriteLine(rdr[0].ToString());
                    Console.WriteLine(rdr[1].ToString());
                }

                rdr.Close();

                ////=============

                commandText = "Update logs Set msg = '123' where msg = 'qaz'; Select SCOPE_IDENTITY()";

                objid = cmd.ExecuteScalar();
                if (objid != DBNull.Value)
                    Console.WriteLine(objid.ToString());
                else
                    Console.WriteLine("NULL!!!"); 

                ////=============


            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                if (rdr != null)
                    rdr.Close();

                if (con != null && con.State == ConnectionState.Open)
                    con.Close();
            }

            Console.Read();

        }
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531752
BlackEric
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не сорри, падает как положено
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531759
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlackEric, а попробуйте изменить триггер
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
ALTER TRIGGER dbo.AI_CheckSingleRow
   ON  [dbo].[logs]
   AFTER INSERT, UPDATE
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	-- SET NOCOUNT ON;

    -- Insert statements for trigger here
	DECLARE @numrows int;
	SET @numrows = 0;

	Select @numrows = count(*) from inserted 
        select @numrows
	IF @numrows > 1
	BEGIN
		ROLLBACK TRAN;
		RAISERROR('Msg cannot be added', 16, 1);
		RETURN;
	END

END
GO

...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39531901
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если для таблицы не предполагается использовать MERGE, то вовсе не нужно селектить количество строк в inserted - достаточно проверить @@rowcount до установки set nocount on (в случае merge ситуация другая ).
А исключение пробрасывается вполне нормально:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create table dbo.Test (n int)
go
create trigger dbo.TrTest on dbo.Test after insert, update
as
begin
  raiserror('rowcount=%d', 0, 0, @@rowcount) with nowait;
  set nocount on;
  rollback;
  raiserror('ARRGH!!111', 16, 1);
end;
go


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
static void Main()
{
  using (var cnn = new SqlConnection("Data Source=.;Initial Catalog=stuff;Integrated Security=True"))
  using (var cmd = new SqlCommand(@"
    insert into dbo.Test
      select number
      from master..spt_values
      where type='P' and number between 1 and 123;
      select 1;",
    cnn))
  {
    cnn.InfoMessage += (s, e) => Console.WriteLine("Server message: {0}", e.Message);
    cnn.Open();
    try
    {
      Console.WriteLine("Scalar result: {0}", cmd.ExecuteScalar());
    }
    catch (Exception e)
    {
      Console.WriteLine("{0}: {1}", e.GetType(), e.Message);
    }
  }
}


в консоли:

Код: plaintext
1.
2.
Server message: rowcount=123
System.Data.SqlClient.SqlException: ARRGH!!111
The transaction ended in the trigger. The batch has been aborted.
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39532101
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlackEricНе сорри, падает как положено

а у меня нет эскцепции
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39532542
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин,

Подключите Profiler и посмотрите попадает ли сервер в блок где у вас raiserror
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39532586
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ffРолг Хупин,

Подключите Profiler и посмотрите попадает ли сервер в блок где у вас raiserror
Не нужен никакой профайлер - raiserror с severity<=10 не прерывает процесс выполнения, и не попадает в блок catch, достаточно его с опцией nowait (чтобы сообщение возвращалось сразу же, а не по окончании всего батча) поместить в блок с rollback, и ловить сообщения от сервера - см. выше мой код.
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533314
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловныfelix_ffРолг Хупин,

Подключите Profiler и посмотрите попадает ли сервер в блок где у вас raiserror
Не нужен никакой профайлер - raiserror с severity<=10 не прерывает процесс выполнения, и не попадает в блок catch, достаточно его с опцией nowait (чтобы сообщение возвращалось сразу же, а не по окончании всего батча) поместить в блок с rollback, и ловить сообщения от сервера - см. выше мой код.

у меня 16
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533316
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупину меня 16
Я видел. Severity>10 - для выбрасывания ошибок, и их обработки в блоке catch (если нужно), severity<=10 - для вывода сообщений.
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533365
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныРолг Хупину меня 16
Я видел. Severity>10 - для выбрасывания ошибок, и их обработки в блоке catch (если нужно), severity<=10 - для вывода сообщений.

Нашел, где я лоханулся,хотя до конца так и не понял причину:

во время отладки триггера оставил пару выборок типа
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select count(*) as totalrows from ....
select count(*) as totalrows2 from ....

а после них уже делаю
IF @numrows>=1
BEGIN
	ROLLBACK TRAN;
	RAISERROR('Msg cannot be added', 16, 1);
	RETURN;
END
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533371
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг ХупинСон Веры Павловныпропущено...

Я видел. Severity>10 - для выбрасывания ошибок, и их обработки в блоке catch (если нужно), severity<=10 - для вывода сообщений.

Нашел, где я лоханулся,хотя до конца так и не понял причину:

во время отладки триггера оставил пару выборок типа
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select count(*) as totalrows from ....
select count(*) as totalrows2 from ....

а после них уже делаю
IF @numrows>=1
BEGIN
	ROLLBACK TRAN;
	RAISERROR('Msg cannot be added', 16, 1);
	RETURN;
END





и это в SSMS и выборки делает и роллбэчится, а при вызове из шарпа тихо отрабатывает и выдает 2 и никакого роллбэка
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533407
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин, роллбак происходит... брехня. не происходит он только если @@rowcount определяется после select count(*)
И да... тах работает скаляр. Получил результат и досвидос... если нужна такого рода богодельня - пользуйте костыли
...
Рейтинг: 0 / 0
c#->SQLServer: Нет Exception при роллбэке в триггере
    #39533409
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин,

ExecuteScalar обрабатывает одну колонку первой строки результирующего набора.
Если возвращаете множественные резалтсеты используйте ExecuteReader()
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / c#->SQLServer: Нет Exception при роллбэке в триггере
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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