How to write a DB-agnostic .NET Core app?
Asked Answered
K

0

6

I'm struggling to port a console app from .NET Framework 4.6.2 to .NET Core 2.0. The app needs to connect to a database whose platform is not known at compile time. In the full framework this was easily achieved by using the DbProviderFactories mechanism which does not exist anymore in .NET Core 2.0.

First, I thought I could simply load the corresponding DbProviderFactory dynamically myself, using code similar to:

public static DbProviderFactory GetFactory(string providerInvariantName)
{
    Type type = Type.GetType(dbProvider.Type);
    if (null != type)
    {
        FieldInfo field = type.GetField("Instance", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
        if (null != field && field.FieldType.IsSubclassOf(typeof(DbProviderFactory)))
        {
            object value = field.GetValue(null);
            if (value != null)
            {
                return (DbProviderFactory)value;
            }
        }
    }
}

as done in this library here. And this code works well as long as the assembly containing the DbProviderFactory is referenced at compile time (which kind of defeats the purpose of dynamic loading).

I tried to just drop System.Data.SqlClient.dll into the app's folder, but then the Instance field is null because this seems to be only a stub implementation of the different runtimes assemblies. When referenced statically, the compiler spits out a verbose .deps.json file that points to those. Here's just minor an outtake to give an impression:

...
"runtime.win-x64.runtime.native.System.Data.SqlClient.sni/4.4.0": {
  "type": "package",
  "serviceable": true,
  "sha512": "sha512-38ugOfkYJqJoX9g6EYRlZB5U2ZJH51UP8ptxZgdpS07FgOEToV+lS11ouNK2PM12Pr6X/PpT5jK82G3DwH/SxQ==",
  "path": "runtime.win-x64.runtime.native.system.data.sqlclient.sni/4.4.0",
  "hashPath": "runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512"
},
"runtime.win-x86.runtime.native.System.Data.SqlClient.sni/4.4.0": {
  "type": "package",
  "serviceable": true,
  "sha512": "sha512-YhEdSQUsTx+C8m8Bw7ar5/VesXvCFMItyZF7G1AUY+OM0VPZUOeAVpJ4Wl6fydBGUYZxojTDR3I6Bj/+BPkJNA==",
  "path": "runtime.win-x86.runtime.native.system.data.sqlclient.sni/4.4.0",
  "hashPath": "runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512"
},
...

This is not something that someone can enter manually.

So what would then be a good way to develop a DB-agnostic app in .NET Core?

Kalinin answered 26/11, 2017 at 10:6 Comment(3)
How many different types of DB does the app actually need to be able to support? If by design it's intended to be configurable to work with any sort of database then there's probably no easy solution until DbProviderFactories support is added to .NET core (which is being worked on).Duthie
@DylanNicholson: it's a relatively closed list of around 5 common RDBMSes. I guess, I could have different versions of the app, compiled against specific providers. But that would be a shame somehow.Kalinin
Maybe I could compile against all possible providers and then somehow only deliver the dependencies as needed when deployed. But I wouldn't know how to do that. This would require something like a "soft dependency" mechanism.Kalinin

© 2022 - 2024 — McMap. All rights reserved.