Our application uses H2Sharp to access a H2 database from C# (Framework v4). H2Sharp inherits DBDataAdapter and implements IDbDataAdapter. As such, what I am asking about most likely applies to SqlDataAdapter, but I wanted to clarify the environment details.
Recently we noticed an issue in accessing the same database on different computers. We have observed the following code sometimes works, sometimes throws an error:
DataRow row;
// Fill the row
String s = row["id"];
The error is "Column id does not belong to table Abcde".
The application works on a computer running Win7 64-bit, Visual Studio 2010 with all the patches. Same binary and database copied to a similar computer gives this error. Interestingly, the code works OK if the line is changed to
String s = row["ID"];
The DataTable
has the "CaseSensitive" property set to false
so initially we could not figure out what is happening.
It turns out that the DataTable
has a "Locale" property and this has a default of the logged user's Locale (as set under the "Format" tab in the "Region and Language" control panel settings on Windows 7). On machines that it does not work, the user locale is set to Turkish and we are seeing a case of the "Turkish I problem" (*).
Now I understand the nature of the problem, I am trying to understand what options I have to solve it. I first thought about if there's a way that I can specify the column names etc be compared in an Invariant culture but the data itself is compared in a given locale. H2 documentation is not very explicit about it but the way it is written, it sounds like the whole database is governed by one main setting. In addition, SELECT * FROM INFORMATION_SCHEMA.COLLATIONS
does not return Unicode, so this option does not seem possible.
In addition, DataTable documentation also suggests the locale is to be used "for string comparisons within the table" so there does not seem to be an option to specify different behavior for column/table names vs user data.
I found this post that mentions this issue and the accepted solution was to use "I" character instead of "i" in the table/column names. However, I think this solution assumes that the code is doing a ToUpper() instead of ToLower() before string comparison, therefore it may be broken if DataTable
code is modified in the future.
That post also has a suggested solution of setting SQL server settings to UTF-8. This looks like a more viable solution. However, I could not find a way to do it for H2 database (both because the setting seems to impact the whole database and there's no UNICODE option).
I appreciate any input/help/guidance.
(*) Turkish I problem: In Turkish, ToUpper(i) == İ, ToLower(I) == (ı)
We went ahead with the suggested solution of using all capital letters in the table/column names. Even though this assumes that the code behind the DataTable
is doing a ToUpper()
instead of ToLower()
for case-insensitive comparison, it seemed unlikely that this code will change its behavior (which would break all the code that uses DataTable
with case-insensitive comparison).