Disabling WCF’s Explicit Element Ordering

If you consume a SOAP web service via WCF, and the service doesn’t return its XML elements in the order specified by its WSDL, you may experience “mysterious null values” in the deserialized response. This is because WCF enforces element ordering for sequences as defined by the XSD standard. If it encounters an element that’s not in the right place it simply gives up.

This is unfortunate if you are consuming a third party web service and you do not have control over the element ordering.

As a workaround you can generate proxies that serialize with XmlSerializer instead of DataContractSerializer, and then remove the element ordering information from the proxy code. Fortunately (with a little help from sed) this can be automated. You’ll need to add a Pre-Build action to your project, and populate it like so:

set proxy_tool="C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SvcUtil.exe" /nologo /t:code /ser:XmlSerializer /UseSerializerForFaults
set sed_tool="$(ProjectDir)sed.exe" -r -i "s/,?[[:space:]]*Order=[[:digit:]]+//"

%proxy_tool%  /o:"Proxy1.cs" /n:*,Namespaces.Name1 "Proxy1.wsdl"
%sed_tool% "Proxy1.cs"

%proxy_tool%  /o:"Proxy2.cs" /n:*,Namespaces.Name2 "Proxy2.wsdl"
%sed_tool% "Proxy2.cs"

...

“The database engine could not lock table ‘…’ because it is already in use by another person or process” error in JET

When performing DML and DDL queries against an Access database you may encounter something similar to the following:

The database engine could not lock table ‘Orders’ because it is already in use by another person or process.

The error message gives some information about one likely cause of this error – somebody else is trying to modify the same table you are. However it’s also possible to get this error message even if you have exclusive access to the database. This example illustrates:

DbConnection connection = Program.OpenAceOleDbConnection("C:\\Temp\\Northwind.mdb");
DbTransaction transaction = connection.BeginTransaction();
DbCommand command = connection.CreateCommand();
command.Transaction = transaction;

command.CommandText = "DELETE FROM [Orders] WHERE [Order ID] < 4000";
command.ExecuteNonQuery();

command.CommandText = "ALTER TABLE [Orders] ADD COLUMN [Test] INT";
command.ExecuteNonQuery();

transaction.Rollback();
connection.Close();

As soon as the second query begins to execute the error is raised:

JET DDL - Locking Exception

JET DDL – Locking Exception

The error message can be produced using JET, ACE and DAO. It is not raised consistently, it appears to be affected by whether the first query modifies row data pages partially or completely. Furthermore, it is only raised when executing queries inside a transaction.

I have not found a good workaround for this problem. If possible, reorder your queries so that the DDL is performed first. Another option is to perform the queries outside of a transaction. In my case, I took advantage of JET’s file-based format and the fact that my application would always have exclusive access to that file and emulated transactions by copying the database to a temporary location, performing the queries and then copying it back.

Update

Q331594 seems to come pretty close to describing this behaviour.

“Operation must use an updateable query” error in JET

When performing update queries against a Microsoft JET database, you may come across the following error:

Operation must use an updateable query

The Microsoft Knowledge Base has an article for the most obvious cause of this error, that the database file is not writable. However, you may also receive this error when trying to run an UPDATE query which contains a subquery:

UPDATE [Orders]
   SET [Status ID] = ( SELECT TOP 1 [Status ID]
                         FROM [Orders Status]
                        ORDER BY [Status ID] );

I encountered this error when trying to write an update query that was valid JETSQL and TSQL. Unfortunately it’s not possible to write the query in a way that is valid SQL on both platforms1 – to work around this error in JET you need to change the way the query is structured:

UPDATE [Orders]
       , ( SELECT TOP 1 [Status ID]
             FROM [Orders Status]
            ORDER BY [Status ID] ) AS [tmpSubquery]
   SET [Orders].[Status ID] = [tmpSubquery].[Status ID];

The query now runs, but we’re not out of the woods yet. Let’s try writing a similar query that would achieve the same thing:

UPDATE [Orders]
       , ( SELECT MIN([Status ID]) AS [Min Status ID]
             FROM [Orders Status] ) AS [tmpSubquery]
   SET [Orders].[Status ID] = [tmpSubquery].[Min Status ID];

This query does not run – it fails with the same error. The problem is our use of an aggregate function (in this case, MIN).

To work around this we must take a departure from ANSI SQL and use the Domain Aggregate functions in Access.

UPDATE [Orders]
   SET [Status ID] = DMin("[Status ID]", "[Orders Status]")

This works, and can even be extended to emulate a correlated subquery via each domain aggregate function’s optional criteria argument.

1 JETSQL and TSQL have differing syntax for update queries. TSQL requires you to use the FROM clause when the update involves multiple tables, JETSQL does not (in line with ANSI SQL). Thus to write an update query that works on multiple platforms you need to use a subquery.

Update

Turns out there is a Knowledge Base article for this problem, for Access 2.0, and describes 3 workarounds. The post above describes the third workaround. Note that the first workaround may not work if you’re inside a transaction (it uses DDL), so I recommend looking at workarounds two and three.

“Add Web Reference” in Visual Studio 2008

Visual Studio 2005 and earlier editions provide excellent support for consuming SOAP web services in any Visual Studio language. Unfortunately, later versions have removed some of this functionality for C++ projects, placing more burden on the developer consuming a web service from C++.

However, if you’re trying to consume a web service from C++ in Visual Studio 2008, it is capable of doing most of the heavy lifting for you, albeit in a more cumbersome fashion.

Let’s take a look at what Visual Studio 2005 offered for consuming SOAP web services in C++, and what later versions do not.

Web References in Visual Studio 2005

In Visual Studio 2005 there is an option to Add Web Reference in the context menu of a Visual C++ project. If you click on it you will be presented with a dialog similar to the one below:

Add Web Reference Dialog

Add Web Reference Dialog

Using this dialog you can find a SOAP web service and Visual Studio will download the discovery and web service definition files. When building your project Visual Studio will invoke SPROXY, a utility that is part of ATL Server. SPROXY generates C++ code for accessing the web service.

For C++ projects, Visual Studio 2005 added a web reference by downloading the discovery and web service definitions files to a folder inside the project and then adding a file filter. The filter’s Unique Identifier property is set to the URL of the web service. After the initial download you can right click on the filter and select Update Web Reference and Visual Studio will fetch the updated definition files. This is shown below.

Update Web Reference Dialog

Update Web Reference Dialog

Web References in Visual Studio 2008

In Visual Studio 2008 this dialog is no longer available for C++ projects, but the underlying functionality remains in the IDE.

To add a web reference to a C++ project in Visual Studio 2008 you will need two things: a copy of ATL Server and your web service definition files.

ATL Server is not included in Visual Studio 2008, although the IDE will still try to invoke SPROXY (and produce an error). You can download the source code from CodePlex and build the SPROXY project. You should add the include folder under Additional Include Directories for any projects that will use ATL. If you are using ATL frequently, copy the include folder somewhere static and add it as an Include files folder under Tools, Options, Projects and Solutions, VC++ Directories.

Make sure that sproxy.exe is added to your PATH, so Visual Studio can find it.

Because the IDE no longer downloads and generates the web service definition files automatically, you have to create these files yourself. At a minimum you will require a .discomap file in addition to the .wsdl and .disco files referenced by it. I recommend using Disco, as it will create all three files. Disco is available from the Visual Studio 2008 Command Prompt.

Once you have SPROXY in place it is a simple matter of adding a new filter to your project, populating the Unique Name property and then adding the three files discussed above. Visual Studio will automatically invoke SPROXY to generate the code your application needs to interact with the web service.

Visual Studio 2008 removes the Update Web Reference option from the context menu, so you will have to update your definition files manually if they change.

Web References in Visual Studio 2010

In Visual Studio 2010 it appears that Microsoft have removed Proxy generator from the list of build tools. While the documentation for Visual Studio 2008 has Proxy generator as step number three, the documentation for Visual Studio 2010 omits this tool. A possible workaround is to write a custom build rule for .discomap files that calls SPROXY.

Error 155005 in Xcode 3

When using Xcode with source code control you may encounter this following message when committing your project:

Error: 155005 (Working copy not locked; this is probably a bug, please report)

In my instance this was caused by placing the build folder under source code control. I use Subversion for source code control, which places a .svn folder inside each folder that is under its control. Xcode was deleting the contents of the build folder when compiling the project, thus deleting the .svn folder and confusing Subversion.

The solution was to remove the build folder from the SVN repository.

Charles Minnow has the writeup, along with an update for Subversion’s config file to make sure it doesn’t happen again:

### Section for configuring miscelleneous Subversion options.
[miscellany]
### Set global-ignores to a set of whitespace-delimited globs
### which Subversion will ignore in its 'status' output, and
### while importing or adding files and directories.
global-ignores = build *.mode1 *.pbxuser *~.nib .DS_Store *~