fsprojects / IfSharp

F# for Jupyter Notebooks
Other
440 stars 71 forks source link

dotnet core + npgsql entity framework core + paket loading issue #231

Open rudihorn opened 5 years ago

rudihorn commented 5 years ago

Description

Trying to load Npgsql entity framework on dotnet core over Paket has issues, most likely related to dependencies not being loaded.

Repro steps

#load "Paket.fsx"
Paket.Package ["Microsoft.EntityFrameworkCore"; "Npgsql"; "Npgsql.EntityFrameworkCore.PostgreSQL"]
#load ".paket/load/netstandard2.0/Npgsql.EntityFrameworkCore.PostgreSQL.fsx"

open Npgsql.EntityFrameworkCore.PostgreSQL
open Microsoft.EntityFrameworkCore

let opt = DbContextOptionsBuilder().UseNpgsql("connectionstring").Options

Expected behavior

It should generate a DbContextOptions.

Actual behavior

type 'Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.NpgsqlDbContextOptionsBuilder' not found in assembly 'Npgsql.EntityFrameworkCore.PostgreSQL, Version=2.2.4.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7'. A possible cause may be a version incompatibility. You may need to explicitly reference the correct version of this assembly to allow all referenced components to use the correct version.

Known workarounds

I sadly could not find one. I've tried loading random further libraries, but with no success.

Related information

cgravill commented 5 years ago

I've just fixed the related issue #232

However, if I switch to using #load "Paket.Generated.Refs.fsx" I get another issue:

image

If I load a dotnet fsi instance there's a similar issue with System.ComponentModel.Composition:

image

So the next question is if that reference is essential, if not why Paket is generating a reference to it. Commenting it out doesn't help unfortunately either.

rudihorn commented 5 years ago

Could it be this reference is just stale? Have you tried running Paket.Clear () first?

With the latest patch I don't get the System.ComponentModel.Composition error, and even if I force load it using Paket it does not solve the "not found in assembly" message.

rudihorn commented 5 years ago

Intellisense hints at:

A reference to the type 'System.Data.Common.DbConnection' in assembly 'netstandard' was found, but the type could not be found in that assembly

rudihorn commented 5 years ago

I've been wanting to also try debugging which libraries are loaded, but trying to access System.AppDomain.CurrentDomain yields the error:

The value, namespace, type or module 'AppDomain' is not defined.

cgravill commented 5 years ago

Good reminder on Paket.Clear() but no change there. It might be a operating system difference that you're not getting the error. Does your main.group.fsx contain #r "System.ComponentModel.Composition"?

I recommend trying to get this working via fsi plus the Paket load scripts. Given it doesn't work there for me, it's unlikely to work in the notebook. It's a lot easier to iterate there.

cgravill commented 5 years ago

Btw if I make a new Visual Studio .NET Core project, add the Npgsql.EntityFrameworkCore.PostgreSQL NuGet then this does work there. So my guess it that this is somewhere between FSI and the load scripts Paket is creating.

rudihorn commented 5 years ago

Hmm let me double check this is not actually related to version incompatability.

Good reminder on Paket.Clear() but no change there. It might be a operating system difference that you're not getting the error. Does your main.group.fsx contain #r "System.ComponentModel.Composition"?

I recommend trying to get this working via fsi plus the Paket load scripts. Given it doesn't work there for me, it's unlikely to work in the notebook. It's a lot easier to iterate there.

My main.group.fsx does not contain System.ComponentModel.Composition. I can also confirm this does not work on fsi, but does work in a new project.

rudihorn commented 5 years ago

@cgravill so it seems that the issue is related due to lazy loading of libraries. Initially none of the libraries are in the current AppDomain, and simply using #r does not do anything but tell the framework that they exist there. The libraries are only loaded when they are referenced, which is troublesome with what seems to be extension libraries. I am able to run the code I would like by running the following code segments in order:

#load "Paket.fsx"
Paket.Version ["Microsoft.EntityFrameworkCore.Design", "2.1.2"; "Npgsql", "4.0.3"; "Npgsql.EntityFrameworkCore.PostgreSQL", "2.1.2"]
#load "Paket.Generated.Refs.fsx"

This one forces the libraries to actually be loaded:

// reference assemblies

let failable f = try f () |> ignore with _ -> ()
failable (fun x -> Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory())
failable (fun x -> Microsoft.Extensions.DependencyInjection.LoggingServiceCollectionExtensions.AddLogging(null))
failable (fun x -> Microsoft.EntityFrameworkCore.RelationalEntityTypeBuilderExtensions.HasDiscriminator(null))
failable (fun x -> Remotion.Linq.Parsing.ExpressionVisitors.MemberBindings.MethodInfoBinding.Bind(null, null))
failable (fun x -> Npgsql.TypeHandling.NpgsqlSafeReadException(null))
failable (fun x ->  Microsoft.EntityFrameworkCore.DbFunctionAttribute())
open Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure
open Npgsql.EntityFrameworkCore.PostgreSQL
open Microsoft.EntityFrameworkCore
let opt = DbContextOptionsBuilder().UseNpgsql("connectionstring").Options
opt.GetType()

Do you have an idea where to best raise this?

cgravill commented 5 years ago

Oh wow yes, that makes a sort of technical sense but seems horrible experience-wise.

Potentially this is a change in moving from .NET Framework to .NET Core? I tested in a .NET Framework notebook and didn't have an issue.

@cartermp any guidance on this?