ericsink / SQLitePCL.raw

A Portable Class Library (PCL) for low-level (raw) access to SQLite
Apache License 2.0
523 stars 109 forks source link

PackageReferencing SQLitePCLRaw.bundle_green on Net6.0 app fails p/invoke #523

Open WilliamXieMSFT opened 1 year ago

WilliamXieMSFT commented 1 year ago

I noticed that the netstandard2.0 version of SQLitePCLRaw.batteries_v2.dll is missing NativeLibraries, but it exists in the net461 copy: image

Since PackageReference uses the targetframework of the app, a .Net6.0 console app will load the netstandard2.0 dll and P/invoking SQLitePCL.raw.sqlite3_load_extension returns with a 1 (SQLITE_ERROR) and a null errmsg. If I change out the netstandard2.0 batteries_v2.dll for the net461 copy, the p/invoke succeeds.

Digging a bit into the source, the e_sqlite3 bundle imports different xmls per framework: SQLitePCL.raw/SQLitePCLRaw.bundle_e_sqlite3.csproj at master · ericsink/SQLitePCL.raw (github.com)

  <Import Condition=" '$(TargetFramework)' == 'netstandard2.0' " Project="..\msbuild_bundle_fragments\e_sqlite3_dllimport.xml" />
  <Import Condition=" '$(TargetFramework)' == 'net461' " Project="..\msbuild_bundle_fragments\e_sqlite3_dynamic.xml" />

For netstandard2.0, e_sqlite3_dllimport.xml just contains packagereferences.

For net461, e_sqlite3_dynamic.xml has the additional nativelibrary_for_netstandard2.cs which I believe would unblock our scenario.

Is there a reason for this discrepancy? Should e_sqlite3_dllimport also compile the nativelibrary_defines.cs and nativelibrary_for_netstandard2.cs? If not, will there be separate defines provided? Thanks for taking a look!


What version of SQLitePCLRaw are you using?

2.1.2 (latest as of this post)

If you are using one of the SQLitePCLRaw bundle packages, which one?

bundle_green

What platform are you running on? What operating system? Which version? What CPU?

Windows 10 - 64-bit Intel chip

What target framework are you building for? Are you on .NET Framework or the newer stuff (.NET Core, .NET 5+, etc)?

Net6.0 (building on Windows but plan to run it on both Windows & Linux)

Are you using the command line, or an IDE? Which IDE? Which version of that IDE?

dotnet 6.0 SDK & VS 2022

Is this problem something that just started happening? For example, were things working well for you and then you updated something and then the problem showed up? What changed?

this worked for framework project which used the batteries_v2.dll from net461, but it broke when I attempt to run in Net6.0 which pulls in the dll from the netstandard2.0 folder.

What is the exact error message you are seeing when the problem happens?

P/invoking SQLitePCL.raw.sqlite3_load_extension returns with a 1 (SQLITE_ERROR) and a null errmsg

Are you using PackageReference or packages.config?

PackageReference

If you are using mobile platforms, are you on classic/legacy Xamarin or on .NET 6 and higher?

N/A

Sometimes other packages using SQLitePCLRaw cause problems when they are mixed together. What other packages are you including in your project?

Just SQLitePCLRaw.bundle_green & SQLitePCLRaw.provider.dynamic_cdecl. We also have a native SqliteExtensions dll that we're trying to load.

How can we reproduce the problem you are seeing? Your issue will get attention much faster if you attach a minimal reproduction sample project.

Basically inspecting SQLitePCLRaw.batteries_v2.dll in the netstandard2.0 and net461 folders using ILDasm

ericsink commented 1 year ago

This may be similar to #490

WilliamXieMSFT commented 1 year ago

It'd be nice to use the netstandard2.0 dll, but our current workaround is to explicitly use the one for net461.

ericsink commented 1 year ago

Taking a second look at this, I think I misunderstood. And unless I misunderstanding yet again, I don't think the nativelibrary code is actually related to the problem.

The real issue here is that the version of the provider used for net6.0 is compiled without support for load_extension.

The code that generates providers has a flag to allow load_extension to be turned on or off:

https://github.com/ericsink/SQLitePCL.raw/blob/d2ac7fd8f086ef01ed4d28d840c194fbab6ef5ca/src/providers/provider.tt#L852-L876

And the gen_providers program sets this flag depending on the various cases. For several common situations, including the one you are getting with net6.0, it's turned off:

https://github.com/ericsink/SQLitePCL.raw/blob/d2ac7fd8f086ef01ed4d28d840c194fbab6ef5ca/gen_providers/Program.fs#L61

But I don't think there is a good reason why it should be. I think I incorporated this feature flag when I implemented load_extension simply to minimize the risk or chance of regression.