NDO Applications run on the Mono platform. While we recommend to use Visual Studio .NET to develop and debug NDO based applications, the NDO.dll, NDOInterfaces.dll and the enhanced assemblies are able to run under mono*.
Let me first give a statement about the motivation, why we chose to make NDO compatible to Mono. We don't think, that there is a big market of .NET developers having to run their applications both under Microsoft .NET and Mono. But customers ask us constantly about the quality of our enhanced code. NDO uses an assembly enhancer, which produces additional code after compiling an assembly in Visual Studio or another compiler tool. While we did hard work in the past to generate code which complies to the .NET Standard and the CLI we didn't have a prove, if the code really complies to the .NET standard. The fact, that NDO applications run under Mono on both Windows and Linux gives us and our customers the assurance, that NDO complies to the .NET standard as described in the ECMA documents.
NDO has nearly 500 hand coded and several thousand automatically generated unit tests. We needed about three man-days to adjust our code that way, that all unit tests run under Mono. Part of this work was writing the NDO provider for PostgreSql.
We found some little differerences between the behavior of Microsoft .NET and Mono which affected our code. And we found a few bugs in our code, which we had to adjust:
1. If you search for private fields using Reflection, Microsoft .NET automatically adds the Flag DeclaredOnly to the BindingFlag NonPublic. That way, if you use NonPublic, you get only the private fields of the current type, not the inherited private fields of the base classes -- which is the case in Mono. To make the code working equal in Microsoft .NET and Mono, you always have to add the flag DeclaredOnly, if you use NonPublic. If you want to get private fields of the base types of your types, you have to iterate through the whole inheritance chain.
2. If you call the method Select() of a DataTable, you might get an array of DataRow objects, which contais null entries. If you try to iterate over all elements of the array using "foreach(DataRow r in rowArray)", you might get an Exception, because null is not convertible in an DataRow object. That might be a bug in Mono.Data or in Npqsql (the ADO.NET provider of the PostgreSql database). We changed the code to eliminate the null entries.
3. There was exactly one wrong IL code sequence which definitely worked under MS .NET, but as far as we understand the standard, shouldn't work. In Mono this code didn'd work, so we had to emit the correct code sequence, which worked both under Mono and Microsoft .NET. Finding out this kind of errors is exactly the point why we made the effort to make NDO running under Mono.
4. NDO used to overwrite the Connection property of the four Command Objects of a DataAdapter during a running transaction. The ADO.NET providers we used so far, didn't have a problem with this behavior, mainly, because it was always the same object, the property was set to. The Npgsql provider doesn't setting the Connection property during running transactions, so we had to change that code.
Because the NDO code showed a different behavior under Mono, we needed some debug information, at least about the source code file and line number where an exception was thrown. So we had to compile our code with the Mono compilers. The good news is, that the gmcs compiler compiled the nearly 100,000 lines of code without complaint. (We used generics in our code.) The bad news is, that there is no way to do source level debugging -- the mono team is working hard on a debugger in these days. If you indend to write applications, which have to run both under Windows and Mono,
- work iteratively
- debug under windows and
- regularly test your applications under mono.
Fazit: With the help of Mono we proved, that NDO complies to the .NET standard. We had to adjust the NDO code at a few places to level out differences between Microsoft .NET and Mono. There was one place, where NDO emitted non-standard IL code, which run under Microsoft .NET but not under Mono. We changed this code sequence, so that it runs under both platforms.
* We used Mono Build 126.96.36.199. All tests were exclusively run with the PostgreSql database.