fsprojects/SQLProvider

Could not load file or assembly 'Microsoft.Extensions.Logging.Abstractions, Version=8.0.0.0

jkone27 opened this issue ยท 25 comments

Describe the bug

The type provider 'FSharp.Data.Sql.SqlTypeProvider' reported an error: Could not create the connection, most likely this means that the connectionString is wrong. See error from Npgsql to troubleshoot: Could not load file or assembly 'Microsoft.Extensions.Logging.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. Could not find or load a specific file. (0x80131621)F# Compiler3033

To Reproduce
.net8, updating an old project to use pgsql instead of mssql

Expected behavior
i would expect it to read the connection, but seems some internal dll library load issue

Screenshots
image

Desktop (please complete the following information):

  • OS: macOs
  • .NET 8.0
  • vscode + ionide

Is this duplicate of #807 ?

seems like,
i also have tried adding
`Microsoft.Extensions.Logging.Abstractions' as extra nuget reference, but does not seem to fix/resolve

see i was able to open Microsoft.Extensions.Logging.Abstractions above at the top

This should help: #807 (comment)

i read the above, do you suggest to add System.Text.Json ?
i already have access to Microsoft.Extensions.Logging.Abstractions but does not seem to help, do we have a working PGSQL sample/integration test in the solution? maybe it can be added to avoid regressions?

dont you think it makes sense to move this whole solution to NET6+ (or NET8+) why support older targets? we are soon in NET9, supporting netstandard is not needed anymore since NET5+

... maybe removing netstandard makes all deps behave consistently for NET6+ versions (would honestly do NET8+ as its latest LTS)

found this but seems like a windows test, trying to see if i mistook anything...
maybe tests should be ran in linux containers for compat with nix users also?

https://github.com/fsprojects/SQLProvider/blob/master/tests/SqlProvider.Tests/scripts/PostgreSQLTests.fsx

do you suggest to add System.Text.Json ?

If you use the latest Postgres drivers, yes, you need that. Either to ResolutionPath or as direct reference to your project.

do we have a working PGSQL sample/integration

The comment had a working zip-file as example. That is not updated to the test-samples: All these DB drivers change so often that it's hard to keep the samples up-to-date. But I'm accepting PRs if anyone wants to update the samples in the solution.

why support older targets?

It seems most of the type-providers target .NET Standard 2.0 and .NET Standard 2.1.
I'd expect that the main reason for that is that TypeProviders have to run also on design-time, so even when you target to new .NET, all the IDEs (like Visual Studio 2022) are not running on those, some are still using the .NET Standard 2.0. So they have to run on both runtimes. (As .NET8 is .NET Standard 2.1 compatible.)

Besides of that, SQLProvider is used by some enterprises (like US Navy, I've heard) and many large enterprises still use the legacy .NET Framework, which has Microsoft guaranteed support longer than any of the new existing .NET. So I'm not seeing to break the backward-compatibility any time soon.

thanks, trying to update this branch of an old project/showcase here, and got a bit stuck
https://github.com/jkone27/FsharpWebApi/blob/update-to-net8-and-pgsql/FSharp/Services/Types.fs

is there ways to automate the creation of this folder somehow, copying from the root nuget folder maybe? i get new "errors" on Microsoft.Bcl.AsyncInterfaces on this latest one...

image

still not working with above suggestions, i add the zip here if interested (based on linked script) / macos gives an error in Microsoft.Bcl.AsyncInteractive 8.0.0 missing

see REPRO folder here >
myTestV2.zip

tried this script, but i notice on MAC i cannot find that Microsoft.Bcl even after adding the library in my project?
https://gist.github.com/jkone27/3752f33a7b365e98ec2fb45d63549e7a

only these libs are found
image

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
    <PackageReference Include="Npgsql" Version="8.0.1" />
    <PackageReference Include="SQLProvider" Version="1.3.23" />
    <PackageReference Include="System.Text.Json" Version="8.0.1" />
    <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
  </ItemGroup>

and even after copying 8.0.0
still cannot load
image

The ReferencePath you probably need .NET Standard 2.0 version of the library and not the .NET8 version, because your VSCode is likely not running on .NET8 yet! Don't worry, the ReferencePath is just for the IDE and compiler, it's not the executable runtime code. So if you target for the .NET8 then the .NET8 libraries should go to the bin-folder (as they go if they are references in the project), but the ReferencePath you need different versions.

i realize now also ionide vscode reports an error in UI which does not match the error of the compiler , which is instead reading 2 errors (datacontext and the type have been created succesfully)
image

cannot make it work i tried copying only netstandard2.0 libs as well...
https://www.nuget.org/packages/Npgsql can anyone produce a working .zip ? here i can see dependent libraries but still cannot troubleshoot also why it does not work in editors.. (tried also vs for mac, but that also does not support net8) a bummer for starter, anyone downloading F# today uses NET8 ...

I was testing your .fsx with my Mac and a few notes:

  • I hate debugging Mac as with Windows VS2022 you can just attach VS2022 to another process of VS2022 (devenv.exe). And then you know what is missing or fails to load. I don't know how to attach a debugger on VS Code with Mac.

  • VS Code seems not to refresh loaded dlls when reference paths are modified, so you need to sometimes restart VS Code for changes to take effect if you modify the ResolutionPath.

  • To make debugging simpler, I added support for semicolon separated ResolutionPath for latest SQLProvider (1.3.28). So instead of copying files manually you can just do something like this:

    [<Literal>]
    let resPath = "~/.nuget/packages/npgsql/8.0.2/lib/netstandard2.0;~/.nuget/packages/system.text.json/8.0.0/lib/netstandard2.0;~/.nuget/packages/system.threading.channels/8.0.0/lib/netstandard2.0;~/.nuget/packages/microsoft.bcl.asyncinterfaces/8.0.0/lib/netstandard2.0;~/.nuget/packages/microsoft.extensions.logging.abstractions/8.0.0/lib/netstandard2.0;~/.nuget/packages/system.memory.data/8.0.0/lib/netstandard2.0;~/.nuget/packages/system.diagnostics.diagnosticsource/8.0.0/lib/netstandard2.0"
  • But referencing files directly from NuGet cache has potential dis-advantage/side-effect that the referenced file might never be loaded with this computer before, and thus not be in the NuGet cache. So you must do also something like this (and execute it once) for system to load the packages:
#r "nuget:Npgsql"
#r "nuget:SQLProvider"
#r "nuget:System.Threading.Channels"
#r "nuget:Microsoft.Bcl.AsyncInterfaces"
#r "nuget:System.Memory.Data"
#r "nuget:Microsoft.Extensions.Logging.Abstractions"
#r "nuget:System.Text.Json"
#r "nuget:System.Diagnostics.DiagnosticSource"

Edit: My Mac doesn't have PostgreSql installed but executing the FSX in FSI got as far as "couldn't connect to localhost"

But referencing files directly from NuGet cache has potential dis-advantage/side-effect that the referenced file might never be loaded with this computer before, and thus not be in the NuGet cache. So you must do also

I was thinking if this is an alternative workaround: add the following entry in your Nuget.config and try to build your solution just once:

<add key="globalPackagesFolder" value="packages" />

(And of course use paths starting with ./packages/... instead of ~/.nuget/packages/....) This looks less ugly than #r FSI script workaround, right?

sorry if i havent replied earlier, i will follow up and test again, thanks for takng this time! @Thorium @knocte ,

In general yes would be much better if this package could all somehow work normally also for beginners is not very easy to use this package correctly, maybe ease of use can be improved with some brainstorming with other F# devs..

maybe is possible to do >multitarget builds/publish packages, and also build for NET8 with simplified dependencies?

much better if this package could all somehow work normally also for beginners is not very easy to use this package correctly

I'm all for that! Especially considering that because of this kind of issues with SqlProvider, my teammates have already been researching for alternatives. But IMO rewriting our data layer is a bigger effort than fixing the root cause of these issues in SqlProvider repo itself. Let's work together to iron this out.

maybe is possible to do >multitarget builds/publish packages, and also build for NET8 with simplified dependencies?

Good question for Thorium, do we want a SqlProvider nuget package that targets more than one framework version?

You want to target .NetStandard 2.0 and 2.1 otherwise the TypeProvider will not work. But separating multiple packages having different databases (SQLProvider.Oracle and so on) could be possibility, then you could easier keep proper driver dependencies. But I'd still keep the current one too, as the dynamic loading with whatever versions is beneficial on some cases.

@Thorium still get error, the error mention connection but right below mention Microsoft.Extensions.Logging.Abstractions ,in my case i have pgsql running locally from docker and connection works perfectly fine, so the problem is def not connection

would you mind trying run DOCKER desktop with PGSQL in it?
also docker could be a nice way to test different db providers
https://hub.docker.com/_/postgres

image

here tested connection works fine
image

still looks like an assembly issue to me, connection seems fine... here full .fsx script

#r "nuget:Npgsql"
#r "nuget:SQLProvider"
#r "nuget:System.Threading.Channels"
#r "nuget:Microsoft.Bcl.AsyncInterfaces"
#r "nuget:System.Memory.Data"
#r "nuget:Microsoft.Extensions.Logging.Abstractions"
#r "nuget:System.Text.Json"
#r "nuget:System.Diagnostics.DiagnosticSource"

open System
open FSharp.Data.Sql
open Npgsql

[<AutoOpen>]
module Settings =

    [<Literal>]
    let resPath = 
        """
        ~/.nuget/packages/npgsql/8.0.2/lib/netstandard2.0;
        ~/.nuget/packages/system.text.json/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.threading.channels/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/microsoft.bcl.asyncinterfaces/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/microsoft.extensions.logging.abstractions/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.memory.data/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.diagnostics.diagnosticsource/8.0.0/lib/netstandard2.0
        """

    // [<Literal>]
    // let resolutionPath = __SOURCE_DIRECTORY__ + "/libraries"

    [<Literal>]
    let connStr = "Host=localhost;Username=postgres;Password=postgres;Database=postgres"

module TestConnectionString = 

    let test () = 
        let conn = new Npgsql.NpgsqlConnection(connStr)
        conn.Open()

        let command = new Npgsql.NpgsqlCommand("select 100;", conn);
        command.ExecuteScalar() :?> int



TestConnectionString.test()

printfn $"{resPath}"

type HR =
    SqlDataProvider<
        Common.DatabaseProviderTypes.POSTGRESQL, 
        connStr, 
        ResolutionPath=resPath, 
        Owner="public">

[<EntryPoint>]
let main arg =
    let ctx = HR.GetDataContext()

    let employeesFirstName =
        query {
            for emp in ctx.Public.Employees do
                select emp.FirstName
        }
        |> Seq.head

    printfn "Hello %s!" employeesFirstName
    0 // return an integer exit code
[<Literal>]
let resPath = 
    """
    ~/.nuget/packages/npgsql/8.0.2/lib/netstandard2.0;
    ~/.nuget/packages/system.text.json/8.0.0/lib/netstandard2.0;
    ~/.nuget/packages/system.threading.channels/8.0.0/lib/netstandard2.0;
    ~/.nuget/packages/microsoft.bcl.asyncinterfaces/8.0.0/lib/netstandard2.0;
    ~/.nuget/packages/microsoft.extensions.logging.abstractions/8.0.0/lib/netstandard2.0;
    ~/.nuget/packages/system.memory.data/8.0.0/lib/netstandard2.0;
    ~/.nuget/packages/system.diagnostics.diagnosticsource/8.0.0/lib/netstandard2.0
    """

Uhmm, there was no .Trim() of these paths when using ;, added now in 1.3.31 version.
But I think the core-issue is that a reference is missing still, e.g. microsoft.extensions.logging.abstractions is having a dependency to Microsoft.Extensions.DependencyInjection.Abstractions, System.Threading.Tasks.Extensions and System.Buffers. We only need the dlls that are actually in use by the database driver npgsql itself, so if they add random dependencies or sub-dependencies which are not in the execution path of the code, that should be ok.

i added the missing dependencies, still does not load Microsoft.Extension.Logging.Abstractions for me

#r "nuget:Npgsql"
#r "nuget:SQLProvider"
#r "nuget:System.Threading.Channels"
#r "nuget:Microsoft.Bcl.AsyncInterfaces"
#r "nuget:System.Memory.Data"
#r "nuget:Microsoft.Extensions.Logging.Abstractions"
#r "nuget:System.Text.Json"
#r "nuget:System.Diagnostics.DiagnosticSource"
#r "nuget: Microsoft.Extensions.DependencyInjection.Abstractions"
#r "nuget: System.Buffers, 4.5.1"
#r "nuget: System.Memory, 4.5.5"

open System
open FSharp.Data.Sql
open Npgsql

[<AutoOpen>]
module Settings =

    [<Literal>]
    let resPath = 
        """
        ~/.nuget/packages/npgsql/8.0.2/lib/netstandard2.0;
        ~/.nuget/packages/system.text.json/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.threading.channels/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/microsoft.bcl.asyncinterfaces/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/microsoft.extensions.logging.abstractions/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.buffers/4.5.1/lib/netstandard2.0;
        ~/.nuget/packages/system.memory/4.5.1/lib/netstandard2.0;
        ~/.nuget/packages/system.memory.data/8.0.0/lib/netstandard2.0;
        ~/.nuget/packages/system.diagnostics.diagnosticsource/8.0.0/lib/netstandard2.0
        """

reloaded multiple times, error is still on logging abstractions, not dependency injection or buffer or memory deps:
image

https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions/

image

is there a way to get this right,
or to have the error be more meaninful and descriptive on what needs to be done to make the TP work?
maybe a more meaningful error pointing to the solution could be already a great help

Thank you so much for your help

Yes I think we can improve the error message. I'll create SQLProvider 1.3.32 and hope that helps.

Btw your path has system.memory/4.5.1/ where it should be system.memory/4.5.5/

Yes I think we can improve the error message. I'll create SQLProvider 1.3.32 and hope that helps.
Btw your path has system.memory/4.5.1/ where it should be system.memory/4.5.5/

@jkone27 were you able to test/fix both things above?

will check again as last time wasnt able to fix actually, thanks a lot for taking this time! but no i wasn't able to fix yet : /

I just released 1.3.36 containing another similar kind of small fix for some other database, but it's common code. so it could help here too.