fsprojects / SQLProvider

A general F# SQL database erasing type provider, supporting LINQ queries, schema exploration, individuals, CRUD operations and much more besides.
https://fsprojects.github.io/SQLProvider
Other
564 stars 144 forks source link

DbProviderFactories #726

Closed JordanMarr closed 3 years ago

JordanMarr commented 3 years ago

Re: #724

I was looking into the idea of passing in an optional DbProviderFactory string as a more standard way of allowing the user to select a Db provider - that way, each provider in SQLProvider could default to the appropriate one, and there could also be an optional "DbProviderFactory" parameter to change it in case there were multiple providers to choose from (like System.Data.SqlClient vs Microsoft.Data.SqlClient, or the two Oracle providers).

The immediate issue I found is that the DbProviderFactories class from .NET framework doesn't exist in netstandard2.0. However, I believe an equivalent can be created using reflection, which is what Telerik has done here: https://docs.telerik.com/reporting/knowledge-base/how-to-register-db-provider-factory-in-net-core-project

Once in place, all the SQLProvider providers could replace their hard-coded and dynamically loaded ADO.NET bits with the swappable DbProviderFactory bits instead. This would still put the onus on the user to pull down the correct Db provider package from NuGet (as opposed to maintaining one package per provider on this end), but it would make the error messages much more obvious since they would be like, "The 'Oracle.ManagedDataAccess.Client.OracleClientFactory' is not installed". Then it would be very obvious to the user how to fix it.

Thorium commented 3 years ago

The policy of SQLProvider has been keeping the dependency hierarchy minimal. That's why the reflection loading. We don't want to include Oracle drivers to your tiny SQLite phone/embedded-device application.

For example, packages 1.1.x has no external dependencies outside the .NET Framework, at all.

Edit: Also, we have to consider the mainainability, we don't want to release new versions every time a driver package changes, but we want people to be able to select their current drivers for new applications.

I was initially thinking releasing the other providers as meta-packages (not supported https://github.com/dotnet/fsharp/issues/6305 ) or minimal hierarchy-packages having a type-provider for a single DB and then dependency to the original SQLProvider, containing only the dependency packages and a few lines of code like:

type OracleProvider<_> = SqlDataProvider<Common.DatabaseProviderTypes.ORACLE, _>

...that would be nice. But I don't know how the editors would then easily treat these meta-packages as typeproviders wihtout getting confused with the original package.