2008-09-11 72 views
2

我目前正在更新允許用戶指定其表之一的模式的一部分的遺留系統。用戶可以通過此界面創建和刪除表中的列。這個遺留系統使用ADO 2.8,並且使用SQL Server 2005作爲它的數據庫(你甚至不想知道在這個野獸現代化嘗試之前它使用了什麼數據庫......但是我離題了)=)更新一個事務中的模式和行,SQL Server 2005

在這個相同的編輯過程中,用戶可以定義(和更改)可存儲在這些用戶創建字段中的有效值列表(如果用戶想限制字段中的內容)。

當用戶更改字段的有效條目列表時,如果他們刪除了其中一個有效值,則允許他們選擇一個新的「有效值」來映射任何具有此(當前無效)值的行它,以便他們現在再次擁有有效的價值。

在瀏覽舊代碼時,我注意到它非常容易讓系統進入無效狀態,因爲上面提到的更改不是在一個事務中完成的(所以如果其他人在上述過程的中途出現上面並做出自己的改變......好吧,你可以想象可能導致的問題)。

問題是,我一直試圖讓它們在單個事務下更新,但是每當代碼到達它改變表的模式的部分時,所有其他更改(更新行中的值,無論是在模式發生變化的表格中,它們甚至可以是完全不相關的表格),直到交易中的這一點似乎都被無聲地丟棄了。我沒有收到任何錯誤消息,表明它們已被刪除,並且當我在最後提交事務時沒有提出錯誤...但是當我查看應該在事務中更新的表時,只有新列在那兒。沒有任何模式更改被保存。

在網上尋找答案迄今已被證明是浪費了幾個小時......所以我轉而尋求幫助。有沒有人曾試圖通過ADO執行事務,它既更新表的架構,也更新表中的行(無論是同一個表還是其他表)?不允許嗎?有沒有任何文件可以在這種情況下有所幫助?

編輯:

好吧,我做了跟蹤,這些命令被送到數據庫(括號中解釋)

(我不知道這裏發生了什麼,看起來像它的創建臨時存儲過程...?)


declare @p1 
int set @p1=180150003 declare @p3 int 
set @p3=2 declare @p4 int set @p4=4 
declare @p5 int set @p5=-1 

(Retreiving保存用戶生成的字段定義信息)表


exec sp_cursoropen @p1 output,N'SELECT * FROM CustomFieldDefs ORDER BY Sequence',@p3 output,@p4 output,@p5 output select @p1, @p3, @p4, @p5 
go 

(我覺得我的代碼是通過這些名單迭代這裏,抓住了當前信息)


exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursorfetch 180150003,1025,1,1 
go 
exec sp_cursorfetch 180150003,1028,1,1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 

(這似乎是在那裏我進入修改數據的定義,我經過每更新發生在定義自定義字段本身的任何變化)


exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=1,@Description='asdf',@Format='U|',@IsLookUp=1,@Length=50,@Properties='U|',@Required=1,@Title='__asdf',@Type='',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=2,@Description='give',@Format='Y',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_give',@Type='B',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=3,@Description='up',@Format='###-##-####',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_up',@Type='N',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=4,@Description='Testy',@Format='',@IsLookUp=0,@Length=50,@Properties='',@Required=0,@Title='_Testy',@Type='',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=5,@Description='you',@Format='U|',@IsLookUp=0,@Length=250,@Properties='U|',@Required=0,@Title='_you',@Type='',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=6,@Description='never',@Format='mm/dd/yyyy',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_never',@Type='D',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 
exec sp_cursor 180150003,33,1,N'[CustomFieldDefs]',@Sequence=7,@Description='gonna',@Format='###-###-####',@IsLookUp=0,@Length=0,@Properties='',@Required=0,@Title='_gonna',@Type='C',@_Version=1 
go 
exec sp_cursorfetch 180150003,32,1,1 
go 

(這是我的代碼刪除通過接口被刪除之前,這些儲蓄開始] ...它也是唯一的事情,據我可以告訴這個交易過程中實際發生的)


ALTER TABLE CustomizableTable DROP COLUMN _weveknown; 

(現在,如果任何定義被改變的方式使用r創建的列的屬性需要更改,或者列上的索引需要添加/刪除,在此完成,併爲給定列中尚未賦值的任何行賦予默認值...值得注意的是,據我所知,這一切都不當存儲過程完成實際情況。)

 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '__asdf' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN __asdf VarChar(50) NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx___asdf') CREATE NONCLUSTERED INDEX idx___asdf ON CustomizableTable ( 
__asdf ASC) WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF); 
go 
select * from IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx___asdf') CREATE NONCLUSTERED INDEX idx___asdf ON 
CustomizableTable (__asdf ASC) WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [__asdf] = '' WHERE [__asdf] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_give' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN _give Bit NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__give') DROP INDEX idx__give ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_give] = 0 WHERE [_give] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_up' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN _up Int NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__up') DROP INDEX idx__up ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_up] = 0 WHERE [_up] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_Testy' 
go 
ALTER TABLE CustomizableTable ADD _Testy VarChar(50) NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__Testy') DROP INDEX idx__Testy ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_Testy] = '' WHERE [_Testy] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_you' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN _you VarChar(250) NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__you') DROP INDEX idx__you ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_you] = '' WHERE [_you] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_never' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN _never DateTime NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__never') DROP INDEX idx__never ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_never] = '1/1/1900' WHERE [_never] IS NULL 
go 
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'CustomizableTable') AND name = '_gonna' 
go 
ALTER TABLE CustomizableTable ALTER COLUMN _gonna Money NULL 
go 
IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[CustomizableTable]') AND name = N'idx__gonna') DROP INDEX idx__gonna ON CustomizableTable WITH (ONLINE = OFF); 
go 
UPDATE CustomizableTable SET [_gonna] = 0 WHERE [_gonna] IS NULL 
go 

(完成交易......?)

 
exec sp_cursorclose 180150003 
go 

畢竟廣告如上所述,只發生列的刪除。事務之前和之後的所有內容似乎都被忽略,並且SQL跟蹤中沒有消息表明事務期間發生了錯誤。

回答

1

代碼使用服務器端遊標,這就是這些調用的用途。第一組調用是準備/打開遊標。然後從光標中提取行。最後關閉遊標。這些sprocs類似於OPEN CURSOR,FETCH NEXT,CLOSE CURSOR T-SQL語句。

我不得不仔細看看(我會這樣做),但是我的猜測是服務器端遊標,封裝事務和DDL有一些問題。

一些其他問題:

  1. 你的意思在這種情況下,使用服務器端遊標?
  2. ADO命令是否都使用相同的活動連接?

更新:

我不能完全肯定發生了什麼事。

看起來您正在使用服務器端遊標,因此您可以使用Recordset.Update()將更改推送回服務器,此外還執行生成的SQL語句以更改模式並更新動態表中的數據S)。使用相同的連接,在一個明確的事務中。

我不確定光標操作會對事務的其他部分產生什麼影響,反之亦然,說實話,我很驚訝這不起作用。

我不知道它會發生多大的變化,但我建議遠離服務器端遊標併爲您的表更新構建UPDATE語句。

對不起,我沒有更多的幫助。

BTW-我發現了sp_cursor呼叫的以下信息:

http://jtds.sourceforge.net/apiCursors.html

0

您描述的行爲是允許的。代碼如何改變架構?動態構建SQL並通過ADO命令執行?還是使用ADOX?

如果您有權訪問數據庫服務器,請嘗試在測試您概述的方案時運行SQL事件探查器跟蹤。查看跟蹤是否記錄任何錯誤/回滾。

+0

哦,它的建設ADO命令。我會嘗試使用跟蹤並報告回來! – EdgarVerona 2008-09-11 23:40:15

+0

好的,用過痕跡,雖然我沒有看到任何異常。 =(我發佈了上面Profiler拾取的SQL語句 – EdgarVerona 2008-09-12 02:19:43