How I managed to connect from Mono in Linux to Oracle
I'm in the process of migrating a ASP.NET MVC application to Mono and Linux. We made the decision to have easier deployment for our clients based on Docker-containers. Looking at Mono's compatibility list, .Net 4.0 and MVC 3 are all supported. Exactly what we needed.
While most parts of the website worked just fine in Mono, data access didn't. At first we needed to migrate from Entity Framework 5 to ServiceStack OrmLite. This turned out to be in many ways also an advantage in the end.
DELETE statements as well as general CRUD was much easier. We implemented most of the rest via Views and Functions in Oracle directly.
At first I was looking at some StackOverflow questions how I could start this:
- How to configure oracle instantclient for mono?
- Can I connect to an Oracle database in a way that will work in a Mono environment (on Linux) and in a ClickOnce deployment (on Windows)?
- How do I use Oracle from .NET?
I tried to use
ServiceStack.OrmLite.Oracle and all the information I got from StackOverflow to access the Oracle database. But it turned out, I was totally of the track. I was in fact so far off that it took me almost half a week to get back and solve this, rather trivial problem. Forget everything written in those posts, the reality is much simpler.
The problem for
ServiceStack.OrmLite.Oracle was, that they referenced the old Oracle client. Not the managed version but the one which exists in an x64 and x86 version and requires the full Oracle client to be installed. Trying out all the tricks didn't help me. I ended up with different exceptions in Linux with libraries missing, file headers being wrong,...
Attention! This solution might bring problems with it if you need timezone aware TimeStamps and TimeSpans in Oracle. Use it with caution.
In the end, I took
ServiceStack.OrmLite.Oracle and modified it to reference Oracle's new managed driver. For it to work, I had to remove the
OracleTimestampConverter, because Oracle's managed driver doesn't have the
GetClientInfo function in the
OracleGlobalization class. The code changes can be seen on GitHub. I've also published these changes as a package on NuGet.
The beauty of this solution is that you don't need anything extra anymore. You can take for instance my Ubuntu-mono Docker image, configure your driver and ConnectionString in
<system.data> <DbProviderFactories> <remove invariant="Oracle.ManagedDataAccess.Client" /> <!-- If any should be in the machine.config --> <add name="Oracle Data Provider for .NET" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=18.104.22.168, Culture=neutral" /> </DbProviderFactories> </system.data> <connectionStrings> <clear /> <add name="OracleContext" providerName="Oracle.ManagedDataAccess.Client" connectionString="DATA SOURCE=<IP_ADDRESS>:1521/XE;PASSWORD=<PASSWORD>;USER ID=<USER_ID>;Connection Timeout=600;Validate Connection=true" /> </connectionStrings>
... and it is WORKING!