CSS SQL Server Engineers

This is the official team Web Log for Microsoft Customer Service and Support (CSS) SQL Support. Posts are provided by the CSS SQL Escalation Services

Conversion issues moving from VS 2005 to VS 2008

Conversion issues moving from VS 2005 to VS 2008

  • Comments 3

I was asked to look at a case yesterday where the customer was hitting the following error after converting a VS 2005 Project to VS 2008.

Error 3 Custom tool error: Failed to generate code. Failed to generate code. Exception of type 'System.Data.Design.InternalException' was thrown. Exception of type 'System.Data.Design.InternalException' was thrown.

This was being produce by an XSD file which was a DataSet based on SQL CE.  Luckily I could reproduce the issue locally with the customer’s project which made digging into this much easier.

Unfortunately, the error displayed above didn’t really give me a lot to go on, but it was an exception so I could get a memory dump.  The thing I love about Managed (.NET) code is that customers can pretty much do the same thing and don’t necessarily need internal symbols.  The Debugging Tools ship with an extension called SOS which you can load to look at things like the Managed Call Stack, and different objects.  To get the dump, you can go about it different ways.  One way would be to use a tool called DebugDiag (available from the Microsoft Download Center) and setup a rule for getting First Chance Exceptions on CLR exceptions. I actually just did a live debug within WinDBG as it was quicker for me to go through that.  I had to sift through a bunch of exceptions until I arrived at the InternalException.  Here was the call stack for the exception (which wasn’t presented in Visual Studio:

 

0:000> !clrstack
OS Thread Id: 0x32cc (0)
ESP       EIP    
002a949c 7614b727 [HelperMethodFrame: 002a949c]
002a9540 6a42ce4a System.Data.Design.ProviderManager.GetFactory(System.String)
002a9568 6a10c881 System.Data.Design.DataComponentMethodGenerator..ctor(System.Data.Design.TypedDataSourceCodeGenerator, System.Data.Design.DesignTable, Boolean)
002a9580 6a10c586 System.Data.Design.DataComponentGenerator.GenerateDataComponent(System.Data.Design.DesignTable, Boolean, Boolean)
002a95ec 6a116e0e System.Data.Design.TypedDataSourceCodeGenerator.GenerateDataSource(System.Data.Design.DesignDataSource, System.CodeDom.CodeCompileUnit, System.CodeDom.CodeNamespace, System.String, GenerateOption)
002a9650 6a140372 System.Data.Design.TypedDataSetGenerator.GenerateInternal(System.Data.Design.DesignDataSource, System.CodeDom.CodeCompileUnit, System.CodeDom.CodeNamespace, System.CodeDom.Compiler.CodeDomProvider, GenerateOption, System.String)
002a96a0 6a14061c System.Data.Design.TypedDataSetGenerator.Generate(System.String, System.CodeDom.CodeCompileUnit, System.CodeDom.CodeNamespace, System.CodeDom.Compiler.CodeDomProvider, GenerateOption, System.String)
002a96d8 6a1406bb System.Data.Design.TypedDataSetGenerator.Generate(System.String, System.CodeDom.CodeCompileUnit, System.CodeDom.CodeNamespace, System.CodeDom.Compiler.CodeDomProvider, System.Collections.Hashtable, GenerateOption, System.String)
002a9714 6a14071f System.Data.Design.TypedDataSetGenerator.Generate(System.String, System.CodeDom.CodeCompileUnit, System.CodeDom.CodeNamespace, System.CodeDom.Compiler.CodeDomProvider, System.Collections.Hashtable, GenerateOption)

That alone tells me a lot.  It looks like we are trying to load a provider and some error is occurring.  Our InternalException.  InternalException still doesn’t tell me what the failure was, but the fact that we are trying to load a Provider narrows the window.  Either we failed to find the provider, or it failed to load assuming we aren’t doing some processing within the GetFactory call itself.

Using .NET Reflector, you can have a look at System.Data.Design.ProviderManager.GetFactory to see what is inside it.  What we are looking for are where we actually throw InternalException.  I saw two places where that happens:

throw new InternalException( string.Format(System.Globalization.CultureInfo.CurrentCulture, "Cannot find provider factory for provider named {0}", invariantName) );

throw new InternalException( string.Format(System.Globalization.CultureInfo.CurrentCulture, "More that one data row for provider named {0}", invariantName) );

Based on this, it was either missing, or there were multiple entries for the provider.  But, what provider?  One thing I know based on the case itself is that it is SQL CE related, so probably a CE Provider. At that point, I typically look at the managed stack to see if I can figure out what that invariantName value is.

0:000> !dso
OS Thread Id: 0x32cc (0)
ESP/REG  Object   Name
002a9430 1776c3bc System.Data.Design.InternalException
002a9440 07f6a388 System.Resources.ResourceReader
002a947c 1776c3bc System.Data.Design.InternalException
002a948c 081902d8 System.String    Microsoft.SqlServerCe.Client
002a9490 1776c3bc System.Data.Design.InternalException
002a9494 1776c3a8 System.Object[]    (System.Object[])
002a94bc 07a71c3c System.String    en-US
002a94c0 1776c3bc System.Data.Design.InternalException
002a94c8 1776c3bc System.Data.Design.InternalException
002a94cc 07a71ccc System.String    en-US
002a94d0 1776c3a8 System.Object[]    (System.Object[])
002a94d8 07a9aabc System.Globalization.CompareInfo
002a94dc 07f6a1e0 System.Resources.ResourceManager
002a94f4 1776c698 System.String    ERR_INTERNAL
002a94f8 1776c3a8 System.Object[]    (System.Object[])
002a94fc 1776c698 System.String    ERR_INTERNAL
002a951c 1776c3bc System.Data.Design.InternalException
002a9524 1776c3bc System.Data.Design.InternalException <- This is where the Exception was thrown
002a9540 07a71b18 System.Globalization.CultureInfo
002a9548 07a71b18 System.Globalization.CultureInfo
002a954c 1776b5fc System.Object[]    (System.Object[])
002a9550 081c6038 System.Data.Design.DesignTable

We can see the Exception, and one of the strings listed is “Microsoft.SqlServerCe.Client”, but it is listed after the Exception was thrown. I could go with that, but I do see an Object Array right before the Exception.  Lets have a look at that to see what is in it.  It may be related.

0:000> !DumpArray 1776b5fc <- could use !da also
Name: System.Object[]
MethodTable: 60ec42b8
EEClass: 60cada64
Size: 20(0x14) bytes
Array: Rank 1, Number of elements 1, Type CLASS
Element Methodtable: 60ef0704
[0] 081902d8

0:000> !do 081902d8
Name: System.String
MethodTable: 60ef0ae8
EEClass: 60cad65c
Size: 74(0x4a) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: Microsoft.SqlServerCe.Client

That looks pretty good to me.  Lets go with “Microsoft.SqlServerCe.Client”.  I started off by doing just a quick Bing search on it.  And I got the following Forum post:

http://social.msdn.microsoft.com/Forums/en-US/vside2008/thread/4b3a423f-1bcb-4a3c-b582-fd3a1f3b3e66/

which lead me to the following forum post:

http://social.msdn.microsoft.com/forums/en-US/sqlce/thread/09ac8a71-a96d-4af2-8a19-43258b6ca7be/

Which based on that, led me to my Machine.Config. In the case of my machine, I do not have a provider listed for “Microsoft.SqlServerCe.Client” within my Machine.Config at C:\windows\Microsoft.NET\Framework\v2.0.50727\CONFIG. I have the following:

<system.data>

<DbProviderFactories>

<add name="Odbc Data Provider" invariant="System.Data.Odbc" description=".Net Framework Data Provider for Odbc" type="System.Data.Odbc.OdbcFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

<add name="OleDb Data Provider" invariant="System.Data.OleDb" description=".Net Framework Data Provider for OleDb" type="System.Data.OleDb.OleDbFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

<add name="OracleClient Data Provider" invariant="System.Data.OracleClient" description=".Net Framework Data Provider for Oracle" type="System.Data.OracleClient.OracleClientFactory, System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

<add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

<add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

<add name="SQL Server Compact Edition Data Provider" invariant="System.Data.SqlServerCe" description=".NET Framework Data Provider for Microsoft SQL Server Compact Edition" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

</DbProviderFactories>

</system.data>

The entry that it is looking for is the following, based on the second forum post.

<add name="SQL Server CE Data Provider" invariant="Microsoft.SqlServerCe.Client" description=".NET Framework Data Provider for Microsoft SQL Server 2005 Mobile Edition" type="Microsoft.SqlServerCe.Client.SqlCeClientFactory, Microsoft.SqlServerCe.Client, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

However, I don’t have that assembly on my machine. I believe this comes from the VS 2005 binaries and I don’t have VS 2005 installed on my machine. The reason the InternalException is being triggered is due to the following line within the XSD:

<Connection ConnectionStringObject="Data Source =&quot;.\mydatabase.sdf&quot;" IsAppSettingsProperty="False" Modifier="Assembly" Name="MyConnectionString" ParameterPrefix="@" Provider="Microsoft.SqlServerCe.Client">

</Connection>

Before opening the 2005 Project in VS 2008, I modified that line within the XSD from “Microsoft.SqlServerCe.Client” to “System.Data.SqlServerCe”. After that, I opened the project in VS 2008 and did not receive the error. It appears to have used a valid provider at that point which allowed the conversion to proceed.

Adam W. Saxton | Microsoft SQL Server Escalation Services
http://twitter.com/awsaxton

Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post
  • Two remarks.

    1. "InternalException" is a rubbish name for any exception type. I hope the team discusses that in the next code review. :-)

    2. I don't have the assemblies handy to fire up Reflector, but it looks like the exception message would contain the provider name. So why doesn't Visual Studio just show that instead of just the exception type, and why couldn't you see it with !dumpobj 1776c3bc instead of groping around on the stack?

  • /agree with point #1

    With regards to point 2, i couldn't actually see it when i dumped out 1776c3bc.  The context wasn't there.  I didn't really spend time to understand why either.  I was also miffed that Visual Studio didn't have it listed, but i think that was just a direct representation of the exception itself, as the exception had the same message without the actual provider which was the pain point.  Had the provider been in the text within Visual Studio, that would have short cutted the whole dump exercise.

  • This is great as an example of using debugging tools, but the fact of the matter is that Visual Studio is the best IDE out there, but the DataSet Designer is the worst part of it. Whoever wrote that should be run over by a bus, buried for a month, exhumed, their rotting corpse doused with gasoline and lit on fire, and their ashes thrown into  a porta-potty at the county fair.

Page 1 of 1 (3 items)