SQL Server 2008 Проблема с SCOPE_IDENTITY () - PullRequest
2 голосов
/ 09 апреля 2010

Мой код не обновляет поле темы. Это ноль. У кого-нибудь есть идеи?

INSERT INTO [Messages]([Sender], [Receiver], [Job_Number], [Subject], [MessageText], [DateSent])
VALUES(@Sender, @Receiver, @Job_Number, @Subject, @MessageText, @DateSent)

SET @ThreadID = SCOPE_IDENTITY()

UPDATE [Messages] 
SET Thread = @ThreadID
WHERE MessageID = @ThreadID

EDIT: Кажется, процедура UPDATE вообще не выполняется. Я даже добавил следующий код в конец sproc, но ничего не обновляется.

UPDATE Comments 
SET SomeField = @ThreadID
where SCID = 33

РЕДАКТИРОВАТЬ:

/****** Object:  Table [dbo].[Messages]    Script Date: 04/09/2010 12:08:55 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Messages](
    [MessageID] [int] IDENTITY(1,1) NOT NULL,
    [Sender] [varchar](30) NOT NULL,
    [Receiver] [varchar](30) NOT NULL,
    [Job_Number] [varchar](20) NULL,
    [Subject] [varchar](200) NULL,
    [MessageText] [varchar](max) NULL,
    [DateSent] [datetime] NULL,
    [Thread] [int] NULL,
 CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED 
(
    [MessageID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[Messages] ADD  CONSTRAINT [DF_Messages_DateSent]  DEFAULT (getdate()) FOR [DateSent]
GO

EDIT: Когда я выполняю хранимую процедуру из Management Studio, обновление работает просто отлично. Проблема в моем приложении, когда я вызываю его с помощью SQLHelper:

SqlHelper.ExecuteNonQuery(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString,
            "spMessagesInsert",
            0,
            message.Sender, 
            message.Receiver,
            message.Job_Number,
            message.Subject,
            message.MessageText,
            message.DateSent
            );

РЕДАКТИРОВАТЬ: В конечном итоге я изменил программный код для вызова хранимой процедуры с использованием Linq-to-sql вместо SqlHelper. Это, казалось, решило проблему.

Ответы [ 4 ]

4 голосов
/ 10 апреля 2010

Возможно, вам не повезло, и вы попали в (в) известную ошибку идентичности / параллелизма, о которой сообщалось в MS Connect , которая теперь является статьей КБ * как для SQL Server 2005, так и для 2008

То есть значение, возвращаемое для SCOPE_IDENTITY, неверно. Код выглядит хорошо, и многие люди смотрели на него, так что, если значение неверно? Это даст те же симптомы, что и вы.

Попробуйте OPTION (MAXDOP 1) на вкладыше, как предложено в статьях

Я сам это видел, так что это не абстрактно и не редко.

2 голосов
/ 09 апреля 2010

«Когда вы устраняете невозможное, что бы ни осталось, каким бы невероятным оно ни было, должна быть правда "

Существует только несколько возможностей, если предположить, что ошибок нет:

  1. Значение не вставляется и не удаляется. Мы можем проверить это, запросив его сразу после Set @ThreadId = SCOPE_IDENTITY()
  2. Транзакция вставки выполняется (например, из транзакции вызывающего кода, из транзакции вызывающего sp). Мы можем убедиться в этом, посмотрев @@TRANCOUNT до и после оператора Update.
  3. Что-то устанавливает столбец Thread в нуль сразу после вашего оператора Update. Мы можем проверить @@ROWCOUNT сразу после заявления об обновлении. Если он равен нулю, то единственная возможность состоит в том, что запись больше не существует. Если это 1, то явно обновление сработало. Сразу после оператора Update вы сможете позвонить Select * From Messages Where MessageId = @ThreadId And Thread Is Not Null и получить запись. Это означает, что если позже в вашем коде снова появится значение Null, то что-то еще изменило его.

Попробуйте следующее:

Set NoCount Off

INSERT INTO [Messages]([Sender], [Receiver], [Job_Number], [Subject], [MessageText], [DateSent])

VALUES(@Sender, @Receiver, @Job_Number, @Subject, @MessageText, @DateSent)

SET @ThreadID = SCOPE_IDENTITY()

-- ensure that the value is not null
Select @ThreadId

-- we should get our record from this query
Select * From Messages Where MessageId = @ThreadId

UPDATE [Messages] 
SET Thread = @ThreadID
WHERE MessageID = @ThreadID

-- we should get 1
Select @@ROWCOUNT

-- we should get a value
Select * From Messages Where MessageId = @ThreadId And Thread Is Not Null

-- are we in a transaction?
Select @@TRANCOUNT

EDIT Еще одним чрезвычайно полезным инструментом для устранения подобных проблем является SQL Server Profiler. Например, вы можете указать ему показывать Rollback Tran completed или Commit Tran completed события вместе с другими операторами SQL и посмотреть, откатывает ли транзакция что-либо.

0 голосов
/ 09 апреля 2010

Я видел эту точно такую ​​же проблему раньше. Решением было включить NOCOUNT в верхней части кода хранимой процедуры (при условии, что он не вызывает нежелательных побочных эффектов для вас):

SET NOCOUNT ON

Кроме того, вы можете установить nocount в SQLHelper для подключения, которое вы используете.

У меня нет всей информации о том, почему это сработало, кроме случаев, когда nocount выключен (т. Е. Подсчитаны строки), кажется, что он «запутывает» следующий оператор обновления (если я получу больше деталей, я обновлю мой ответ позже). Произошло то же самое, что вы описали ... следующий оператор UPDATE никогда не выполнялся, и тем более, что хранимая процедура неожиданно завершилась (основываясь на том, что было записано в SQL Profiler).

0 голосов
/ 09 апреля 2010

Проверьте таблицу сообщений на наличие триггеров.


SET @ThreadID = SCOPE_IDENTITY() 

PRINT convert(varchar(30), @ThreadID)

UPDATE [Messages]  
SET Thread = @ThreadID 
WHERE MessageID = @ThreadID 

Он печатает, что вы ожидаете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...