When using SMO in a multithreaded environment (but with different instances on each thread, nothing shared on our side), the IScriptable.Script call sometimes fails in SqlSmoObject.GetQueryTypeKeyFields: Microsoft.SqlServer.Management.Smo.FailedOperationException: Script failed for Table 'dbo.XXXX'. ---> Microsoft.SqlServer.Management.Smo.FailedOperationException: Script failed for Table 'dbo.XXXX'. ---> System.ArgumentException: An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.GetQueryTypeKeyFields(Type t) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.GetQueryTypeKeyFieldsCount(Type t) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.InitObjectsFromEnumResultsRec(SqlSmoObject currentSmoObject, XPathExpression levelFilter, Int32 filterIdx, IDataReader reader, Int32 columnIdx, Object[] parentRow, Boolean forScripting, List`1 urnList, Int32 startLeafIdx) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.AdvanceInitRec(SqlSmoObject currentSmoObject, XPathExpression levelFilter, Int32 filterIdx, IDataReader reader, Int32 columnIdx, Int32 columnOffset, Object[] parentRow, Boolean forScripting, List`1 urnList, Int32 startLeafIdx) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.InitObjectsFromEnumResultsRec(SqlSmoObject currentSmoObject, XPathExpression levelFilter, Int32 filterIdx, IDataReader reader, Int32 columnIdx, Object[] parentRow, Boolean forScripting, List`1 urnList, Int32 startLeafIdx) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.AdvanceInitRec(SqlSmoObject currentSmoObject, XPathExpression levelFilter, Int32 filterIdx, IDataReader reader, Int32 columnIdx, Int32 columnOffset, Object[] parentRow, Boolean forScripting, List`1 urnList, Int32 startLeafIdx) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.InitObjectsFromEnumResultsRec(SqlSmoObject currentSmoObject, XPathExpression levelFilter, Int32 filterIdx, IDataReader reader, Int32 columnIdx, Object[] parentRow, Boolean forScripting, List`1 urnList, Int32 startLeafIdx) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.InitObjectsFromEnumResults(Urn levelFilter, IDataReader reader, Boolean forScripting, List`1 urnList, Int32 startLeafIdx, Boolean skipServer) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.InitChildLevel(Urn levelFilter, ScriptingOptions so, Boolean forScripting) at Microsoft.SqlServer.Management.Smo.Database.PrefetchObjects(ScriptingOptions options, IEnumerable`1 filters) at Microsoft.SqlServer.Management.Smo.Scripter.PrefetchDependencyCollection(DependencyCollection depList) at Microsoft.SqlServer.Management.Smo.Scripter.ScriptWithListWorker(DependencyCollection depList, SqlSmoObject[] objects) at Microsoft.SqlServer.Management.Smo.Scripter.ScriptWithList(DependencyCollection depList, SqlSmoObject[] objects) --- End of inner exception stack trace --- at Microsoft.SqlServer.Management.Smo.Scripter.ScriptWithList(DependencyCollection depList, SqlSmoObject[] objects) at Microsoft.SqlServer.Management.Smo.Scripter.Script(Urn[] urns, SqlSmoObject[] objects) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.EnumScriptImpl(ScriptingOptions so) --- End of inner exception stack trace --- at Microsoft.SqlServer.Management.Smo.SqlSmoObject.EnumScriptImpl(ScriptingOptions so) at Microsoft.SqlServer.Management.Smo.SqlSmoObject.ScriptImpl(ScriptingOptions so) at <our code> MAIN ASSEMBLY INFORMATION: Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91File: C:/Windows/assembly/GAC_MSIL/Microsoft.SqlServer.Smo/10.0.0.0__89845dcd8080cc91/Microsoft.SqlServer.Smo.dllInternalName: Microsoft.SqlServer.Smo.dllOriginalFilename: Microsoft.SqlServer.Smo.dllFileVersion: 10.0.2531.0 ((Katmai_PCU_Main).090329-1045 )FileDescription:Product: Microsoft SQL ServerProductVersion: 10.0.2531.0Debug: FalsePatched: FalsePreRelease: FalsePrivateBuild: FalseSpecialBuild: FalseLanguage: Language NeutralThis bug reproduction wasn't predictable since it seems to require at least two threads entering the SqlSmoObject.GetQueryTypeKeyFields at nearly the same time (and on the same Type, e.g. StoredProcedure).Hence, the bug reproduction may require some many-cores configuration (eight cores in our case, running two quad cores CPUs).First thoughts go to a missing key check between a lock acquirement and a Dictionary.Add call.
Version
Category
Operating System