Solving Error : BAM deployment failed : The locale identifier (LCID) 8192 is not supported by SQL Server

When trying to deploy a BAM activity on a BizTalk Server 2020 machine, I had the following error: BAM deployment failed : The locale identifier (LCID) 8192 is not supported by SQL Server

Error Description

The following BAM command:

bm deploy-all -DefinitionFile:MyActivity.xml

Returns the following error:

Deploying Activity… ERROR: The BAM deployment failed.
A .NET Framework error occurred during execution of user-defined routine or aggregate "deploy_project_internal":
System.Data.SqlClient.SqlException: The locale identifier (LCID) 8192 is not supported by SQL Server.
System.Data.SqlClient.SqlException:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.DispatchMessages(Boolean ignoreNonFatalMessages) at System.Data.SqlClient.SqlDataReaderSmi.InternalNextResult(Boolean ignoreNonFatalMessages) at System.Data.SqlClient.SqlDataReaderSmi.NextResult() at System.Data.SqlClient.SqlCommand.RunExecuteReaderSmi(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteScalar()
at Microsoft.SqlServer.IntegrationServices.Server.ServerConnectionControl.GetServerProperty(String propertyName)
at Microsoft.SqlServer.IntegrationServices.Server.ServerConnectionControl.GetSchemaVersion()
at Microsoft.SqlServer.IntegrationServices.Server.ISServerExecArgumentBuilder.ToString()
at Microsoft.SqlServer.IntegrationServices.Server.ServerApi.DeployProjectInternal(SqlInt64 deployId, SqlInt64 versionId, SqlInt64 projectId, SqlString projectName)

After a little bit of Googling, I found someone having a different issue but with what looked like the same root cause (see Marc van der Wielen blog post here).
I detail the solution here again in case that one day Marc’s blog goes down. All credit goes to him.

Error root cause

The root cause of the problem is that the Service Account running the SQL Server instance is using an (apparently) unsupported locale setting.

In my case, my Windows 10 machine is configured with en-BE (English-Belgium) locale. I installed MS SQL Server with mostly all default options. By doing so, the Service Account created by the installer took the en-BE locale setting.
Once I changed the locale setting of the Service Account to en-US, the error hereabove disappeared.
It looks like while SQL Server did run fine for everything so far, it needs to have the local settings of the Service Account set to en-US for some specific functionalities to work properly (such as publishing a BizTalk BAM Activity in my case).

Resolution Procedure

1. Find what is the Service Account running the MS SQL Server service.
We can find that easily by running services.msc from a prompt.
When we find the SQL Server service, we can just look at its properties to see the name of the Service Account used to run it:

Finding SQL Server Service Account Name

2. Find the SID (Security Identifier) of the Service Account.
One way to do this is through the registry:
– Open the registry by running regedit from a prompt.
– Once in the registry editor, navigate to the following registry node: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
– The registry node contains a list of nodes having SIDs as name. Find the node for which the ProfileImagePath‘s entry contains the MSSQLSERVER value. Write down the SID, in my case it is S-1-5-80-3880718306-xxxxx.

Another way to find the SID is to use PowerShell:
The PowerShell command is slightly depending of the type of account running the SQL Service (local account or domain account), see details here.

For local accounts:
>$objUser = New-Object System.Security.Principal.NTAccount("NT Service\MSSQLSERVER")
>$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
>$strSID.Value

For Domain account we get the NTAccount object in the following way:
>$objUser = New-Object System.Security.Principal.NTAccount(DOMAIN_NAME, USER_NAME)

3. Change the Service Account locale setting.
Navigate to the following registry node folder (using your own SID from the previous step): Computer\HKEY_USERS\S-1-5-80-3880718306-xxx\Control Panel\International.
– Set the Locale entry value to “00000409
– Set the LocalName entry value to “en-US
– Restart the SQL Server Service.

Set SQL Server Service Account Locale

Setting the local setting for new user accounts to be of a particular locale

To avoid having this kind of issue, it is possible to tell Windows to set the default locale for new accounts. This option is in the Control Panel -> Regions -> Administrative -> Welcome screen and new user accounts.

This is also scriptable. See : https://docs.microsoft.com/en-US/troubleshoot/windows-client/deployment/automate-regional-language-settings

Failure to configure BizTalk BRE on named SQL Server instance‏.

I was installing BizTalk on a multi server environment and it failed while configuring BizTalk Server Business Rules Engine (BRE) with an error I never had before so I thought to write a little post about it in case it helps someone some day.

The infrastructure was as follow:

  • BizTalk Server: Windows Server 2008.
  • SQL Server: Windows Server 2008 cluster (2 nodes).
  • The SQL Server was clustered, running on a named instance on a custom port (instead of the default TCP port 1433).
  • There is a Firewall between the BizTalk Server and SQL Server with only the necessary ports open.
  • SQL Browser is not running.

Symptoms:

When configuring BizTalk Server; Enterprise SSO, BizTalk Group, the BizTalk runtime and all their respective databases could be configured successfully but the BRE (Business Rules Engine) failed to be configured correctly.

When looking at the log file, I saw the following error:

[ Error RulesEngine] System.Net.Sockets.SocketException (0x80004005): No such host is known at System.Net.Dns.GetAddrInfo(String name) at System.Net.Dns.InternalGetHostByName(String hostName, Boolean includeIPv6)

Solution:

This was quite puzzling as I could not see why all BizTalk services and Databases could be configured correctly except for BRE. The only thing I could think of from the error message was that the tool configuring BRE was using a different way to connect to the SQL Server machine.
While defining the SQL Server Name in the BizTalk Server Configuration tool, I used the following syntax:
<SQLServerName>,<PortNumber>\<SQLInstanceName>.
I then tried to reconfigure BRE using an alternative syntax I knew of:
<SQLServerName>\<SQLInstanceName>,<PortNumber>.
This did the trick and BRE got configured correctly. As I said before, this is probably due to the underlying API used to connect to the SQL Server box.

As it was a little disturbing for me that the former syntax works in most cases (and particularly in SQL Server Management Studio) but does not work for the Business Rule Engine part of BizTalk Server configuration, I decided to dig out a little more to find out what was the actual canonical syntax. After a quick research, I realized that it is redundant to specify both the SQL Server Instance Name and the port number because a SQL Server instance is mapped to only one TCP port. This is actually what SQL Browser does, it converts the Instance Name to the TCP port number the Named Instance listens to. On a side note, SQL Browser will map the Instance Name to a named pipe when using the named pipe protocol instead of TCP.
So the actual canonical syntaxes are either:

  • <SQLServerName>\<SQLInstanceName> in case SQL Browser is running.
  • <SQLServerName>,<PortNumber> for TCP connection in case SQL Browser is not running.
  • <SQLServerName>\<pipe>\<pipename> for named pipe connections in case SQL Browser is not running.

Conclusion:

I shall stick to the canonical syntax instead of using uncommon alternatives, especially the one I was using: <SQLServerName>,<PortNumber>\<SQLInstanceName>.

References:

SQL Server Browser Service

SqlConnection.ConnectionString Property

 

SQL Server and .Net Data Type mapping

Today I would like to post a table listing the corresponding .Net Type to use with each SQL Data Type. This comes in handy when writing ADO.NET code.

The following link lists Microsoft SQL Server data types and their equivalent data type in .Net.
To be more exact it lists:

  • Every SQL Server data types
  • Their equivalent in the Common Language Runtime (CLR) for SQL Server in the System.Data.SqlTypes namespace
  • Their native CLR equivalents in the Microsoft .NET Framework

SQL Server Data Types and Their .NET Framework Equivalents

I have also copy-pasted the SQL Server and .Net Data Type mapping table hereunder for my own convenience:

SQL Server data type CLR data type (SQL Server) CLR data type (.NET Framework)
varbinary SqlBytes, SqlBinary Byte[]
binary SqlBytes, SqlBinary Byte[]
varbinary(1), binary(1) SqlBytes, SqlBinary byte, Byte[]
image None None
varchar None None
char None None
nvarchar(1), nchar(1) SqlChars, SqlString Char, String, Char[]
nvarchar SqlChars, SqlString SQLChars is a better match for data transfer and access, and SQLString is a better match for performing String operations. String, Char[]
nchar SqlChars, SqlString String, Char[]
text None None
ntext None None
uniqueidentifier SqlGuid Guid
rowversion None Byte[]
bit SqlBoolean Boolean
tinyint SqlByte Byte
smallint SqlInt16 Int16 (short in C#)
int SqlInt32 Int32 (int in C#)
bigint SqlInt64 Int64 (long in C#)
smallmoney SqlMoney Decimal (decimal in C#)
money SqlMoney Decimal (decimal in C#)
numeric SqlDecimal Decimal (decimal in C#)
decimal SqlDecimal Decimal (decimal in C#)
real SqlSingle Single (float in C#)
float SqlDouble Double (double in C#)
smalldatetime SqlDateTime DateTime
datetime SqlDateTime DateTime
sql_variant None Object
User-defined type(UDT) None Same class that is bound to the user-defined type in the same assembly or a dependent assembly.
table None None
cursor None None
timestamp None None
xml SqlXml None

Regarding CLR Data Types, Data Types are basically divided in 3 categories:

Furthermore, 3 types of CLR Data Type structures exist to hold numeric values:

See Data Types (C# Reference) for a complete reference and correspondance between CLR types and C# types.

SQL Server Execution Plan Tutorial

Here is a great article written by Grant Fritchey on the basics of analyzing execution plans on SQL Server. It is actually the first chapter of his book on the topic. Yes, a whole book on SQL Server Execution Plans! I haven’t read the whole book but it should probably reveal itself very interesting for DBAs.

Most of us are familiar with the graphical representation of execution plans but Grant Fritchey shows us how to also get execution plans in an XML format and how they actually give more information that their graphical counterpart.

XML executions plans can be saved into files (.sqlplan) and can be viewed either in their XML form or in a graphical form. Being able to save execution plans in a file is very convenient as it makes it easy to share it with DBAs and peers to ask them about their opinion on a slow running query.

Note that on my machine I actually had to edit the .sqlplan file as the first line of the file was a piece of text reading “Microsoft SQL Server 2005 XML Showplan”. This made that the XML file was not well-formed and so could not be loaded by SQL Server Management Studio – this might be fixed in a later Service Pack or hotfix. Once I removed the line of text, I could successfully open the .sqlplan file in SQL Server Management Studio and see the graphical representation of the execution plan. I could also open the file in a text or XML editor and thus see the execution plan in a textual manner. I think that both approaches can prove themselves being complimentary.

The article also shows us how to collect XML execution plans through SQL Server 2005’s Profiler tool. Once execution plans are collected from the server they can be analyzed by DBAs and developers. This can reveal very useful when you want to profile and analyze activities on production environment where you can’t play with data as freely as on a development environment.

For my own sake, I have summarized the introductory materials on the topic hereunder. You might choose to not read it as it is anyway based on the article written by Grant Fritchey.

Execution Plan Introduction.

When you are tuning T-SQL code for performance on SQL Server, the most important information available to you is the Execution Plan. It tells you what kind of JOIN operations and other algorithms are executed as well as what indexes are used. This kind of information will reveal being crucial on poorly performing queries that you need to optimize.

Please keep in mind that this discussion is focused on DML T-SQL.

DML stands for Data Manipulation Language and is aimed at fetching or manipulating data. Basically, it is any SELECT, INSERT, UPDATE and DELETE statement.

DDL stands for Data Definition Language and is aimed at defining data structures. Basically, it is any CREATE, DROP and ALTER statement. DDL statements do not need any query optimization because there is always only 1 way to execute those statements. For example, there is only 1 way to create a table or an index.

When executing a T-SQL query, the T-SQL code is interpreted into instructions understandable by the Database engine. The Database engine is made of multiple processes/sub-engines but 2 are of particular interests regarding Execution Plans: the Relational Engine and the Storage Engine.

Note that in the context of this text, a Process does NOT mean a Windows Process but rather has the more generic meaning of a collection of instructions processing some data. It can be seen as a software module or component.

The Relational Engine.

The Relational Engine is responsible for 3 processes which are of interest in our study:

  • The Parser. The Parser receives the T-SQL query as input and outputs a parse tree or query tree. The parse tree represents the logical steps necessary to execute the query.
  • The Algebrizer. The Algebrizer receives the parse tree from the Parser process as input and resolves all datatypes, names, aliases and synonyms. The output is binary information called the query processor tree.
  • The Query Optimizer. The query optimizer is a piece of software that models the way in which the database relational engine works. Using the query processor tree together with the statistics it has about the data and applying the model, the Query Optimizer works out heuristically what it thinks will be the optimal way to execute the query – that is, it generates an optimized estimated execution plan.

The Storage Engine.

The Storage Engine will execute the estimated execution plan except if it judges that it should be modified. It could be the case if:

  • The estimated execution plan exceeds the threshold for parallel execution.
  • The statistics used to generate the plan are out of date.
  • The estimated execution plan is invalid (for example it creates temp table and so contains DDL statement)

The final execution plan, called the actual execution plan is what is actually executed by the Storage Engine. It might or might not be the same as the estimated execution plan.
Note that generally, there won’t be any differences between the esti¬mated and actual execution plans.

Execution Plan Cache.

As it is expensive for the Server to generate execution plans, SQL Server will keep and reuse plans wherever possible. As they are created, plans are stored in a section of memory called the Plan Cache.

Once the estimated execution plan is created, and before it gets passed to the storage engine, the optimizer compares this estimated plan to actual execution plans that already exist in the Plan Cache. This reuse avoids the overhead of creating actual execution plans. This is obviously beneficial for large and complex queries but also for simple queries which could potentially be called very often (hundreds or thousands of time).

Execution Plans can be removed from the cache in the following scenarios:

  • Memory is required by the system.
  • The “age” of the plan (its time-to-live) has reached zero.
  • The plan isn’t currently being referenced by an existing connection.

Also, cached execution plans might not be reused if an execution plan needs to be recompiled. Certain events and actions can cause a plan to be recompiled. Grant Fritchey enumerates those events in his article.