在做站点复制的时候,发现有时候会出现“System.Data.SqlClient.SqlException: 违反了 PRIMARY KEY 约束 'PK__#ExportObjects____52593CB8'。不能在对象 'dbo.#ExportObjects' 中插入重复键。”的错误:
message: System.Data.SqlClient.SqlException: 违反了 PRIMARY KEY 约束 'PK__#ExportObjects____52593CB8'。不能在对象 'dbo.#ExportObjects' 中插入重复键。
语句已终止。
在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
……(略去)
我的版本为MOSS 2007 SP1,在Technet上搜索该错误,发现有一个讨论比较多的帖子:http://social.technet.microsoft.com/forums/en-US/sharepointadmin/thread/2e13998b-5cec-4201-b1b4-03b0d7b701c1/,最终的结论是这是WSS的一个Bug,有一个Hotfix可以解决(KB950279),大家可以通过如下地址下载该补丁:http://support.microsoft.com/kb/950279,相信遇到这个问题的朋友大部分可以解决该问题了。
但是遗憾的是,我的问题仍然没有解决,甚至将WSS升级到SP2仍然无济于事。
经过仔细的分析研究,终于找到了问题所在:
微软在升级到SP1的时候,由于版本规则产生了变化,因此对SPListItem的导出做了调整,而导出是先放入到临时表里面“#ExportObjects”,微软却没有及时更新Content Deployment模块,致使当一个SPListItem包含多个版本的时候,由于各个版本guid相同,在用存储过程“proc_DeplAddListItem”插入临时表的时候出错,于是通过Hotfix:950279更新了该存储过程,但是遗憾的是,950279却没有更新存储过程“proc_DeplAddFolder”,即没有对SPFolder做调整,因此,对于由SPFolder继承来的内容类型,如果有多个版本的话,就会产生上面的错误。
上面是我的个人判断,实际测试时,当folder类型的对象只有一个版本的时候,导出成功,当包含多个版本的时候,导出出错,因此证实了我的推断基本上是正确的。希望微软能及时更新此问题。
但是我没有时间等微软发布新的Hotfix,而且也许大多数应用不会用到SPFolder对象的版本,问题还得自己解决,解决的办法我曾想过在导出的对象上加上属性:
“settings.IncludeVersions = SPIncludeVersions.LastMajor;”
发现也不行,因为对SPFolder继承来的Content type根本不起作用,于是只好更改MOSS系统本身提供的存储过程:proc_DeplAddFolder
解决办法:
打开存储过程(数据库/相应的数据库实例/可编程性/系统存储过程):
找到proc_DeplAddFolder,将其中的:
SELECT
Docs.Id,
CASE
WHEN Docs.DocLibRowId IS NOT NULL THEN 6
ELSE 2
END,
0,
Docs.DirName,
Docs.LeafName,
Docs.ParentId,
Docs.WebId,
@IncludeDescendants,
@IsLink,
改为:
SELECT DISTINCT
Docs.Id,
CASE
WHEN Docs.DocLibRowId IS NOT NULL THEN 6
ELSE 2
END,
0,
Docs.DirName,
Docs.LeafName,
Docs.ParentId,
Docs.WebId,
@IncludeDescendants,
@IsLink,
即在Select后面加了一个:DISTINCT(加黑斜体字),就可以了,经过测试成功!
由于能力和时间所限,没有再深入研究该存储过程,如果能有更完善的解决办法,希望告知。