System.Data.SQLite
View Ticket
Not logged in
Ticket UUID: f0246d1817c04078b80ad45a641876fce19291f7
Title: x86/x64 Interop location
Status: Closed Type: Feature_Request
Severity: Important Priority: Medium
Subsystem: Integration_Via_PInvoke Resolution: Fixed
Last Modified: 2013-12-31 07:45:31
Version Found In: 1.0.90.0
User Comments:
anonymous added on 2013-12-24 10:07:13:
In XCOPY deployment scenarios where binaries are distributed over several subfolders it is impossible to reuse a single System.Data.SQLite binary set due to the search mechanism used to locate the Interop libraries.

Currently the location of the process is used as the reference point for the x86/x64 interop folders, however this demands that at least the x86/x64 folders are present in every folder where a binary is referencing the SQLite assembly.

A .config file can of course be used to point to a shared SQLite assembly in a common location, but the interop files still need to be copied to every subfolder.

I was able to work around this issue by changing line 283 in UnsafeNativeMethods.cs (checkin: f89efea9e942e714) to:

Assembly assembly = Assembly.GetExecutingAssembly();

It does however look like the search mechanism for the interop quite deliberately uses the location of the executing assembly rather than SQLite assembly when looking for the x86/x64 interop libraries...

mistachkin added on 2013-12-25 02:06:52:
The Assembly.GetExecutingAssembly call should return the assembly containing
the method currently being executed, not necessarily the one that started the
process.  Please see:

[http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getexecutingassembly%28v=vs.110%29.aspx]

The method that returns the assembly that started the process is Assembly.GetEntryAssembly, described here:

[http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getentryassembly%28v=vs.110%29.aspx]

I'm not sure what changes are being proposed by this ticket; however, I'm open
to suggestions on how to improve the native library search mechanism.

anonymous added on 2013-12-25 08:51:24:
If I understood correctly the author of the ticked wants it all to work by default as if PreLoadSQLite_UseAssemblyDirectory is defined. The current default is different - x64 and x86 are searched as subdirectories of "the main application" (and x86 and x64 have to be duplicated for each application).

I am still evaluating various scenarios. But so far I rather agree with the author, I would prefer PreLoadSQLite_UseAssemblyDirectory by default and the current behavior optional via another env variable.

--
Roman

mistachkin added on 2013-12-26 00:09:21:
Changing that default would not be backwards compatible; however, I'm working on
an alternative solution to make the native library pre-loading more flexible.

anonymous added on 2013-12-26 20:01:40:
Thank you for trying to improve loading of the native interop DLLs.

A thought and a suggestion to consider. System.Data.SQLite by default can search for x86 and x64 in both the application base and the executing assembly (System.Data.SQLite) directories. This approach is not something new, it is a known practice. This is similar to what .NET itself does when it resolves a reference to an assembly. At first it searches in the application base directory, then in extra directories specified in the app.exe.config file, if any, then it searches in the executing assembly directory (which requires a referenced assembly to be loaded, analogue of System.Data.SQLite in our case), then only it fails.

This approach might be generalized for loading interop DLLs (with adjustments for x86/x64 subdirectories, of course). In none of the special env variables is specified then it searches in app_base/x86|x64, then in <System.Data.SQLite dir>/x86|64.

--
Roman

mistachkin added on 2013-12-27 11:07:28:
There is now a prototype of this type of search present on the
"refactorNativeLibraryPreLoader" branch, see check-in [ae2e6767b5].

This new feature is disabled by default, it can be enabled by setting the
"PreLoadSQLite_SearchForDirectory" environment variable [to anything].

anonymous added on 2013-12-27 11:42:27:
It sounds good, thank you for doing this.

Nevertheless, to me and to the same class of users this does not add much value if this is disabled by default. I had to set an environment variable and I still have to set an environment variable (the same or another). It would be a more noticeable improvement if several directories are searched by default, so I do not have to care of setting variables. Besides, I already know that my DLLs are in the executing assembly place (I set PreLoadSQLite_UseAssemblyDirectory) - so why would I want to change this for search in more directories? Thus, I will stay with my PreLoadSQLite_UseAssemblyDirectory, i.e. nothing changes.

Can this be a breaking change to search in several directories *by default*? It is very unlikely. Even performance will not change for those who keep their DLLs in the app base dir, their are found their first during the search.

The thing is that many users do not read all the details in the manual even on issues (like in this ticket's case, perhaps). So it would be nice to minimize those issues in the first place. A way to do this is to search for interop DLLs in several places. If an advanced user wants to change this (i.e. something that is working for him anyway, that's why an *advanced* user) then he will find a way in the manual and will set a proper variable.

I am a casual user and it's possible that I do not see the whole bigger picture. I am not criticizing the great product in any way, I am just thinking of how to make it easier to use.

--
Roman

mistachkin added on 2013-12-27 11:46:15:
Actually, the setting in question can also be placed in the newly supported XML
configuration file (i.e. "System.Data.SQLite.dll.config") in the directory that
contains the System.Data.SQLite managed assembly.

I'm currently considering changing the default behavior; however, I was hoping
to mitigate the risk and let people use these new semantics for a few releases
prior to taking that step.

anonymous added on 2013-12-27 13:05:01:
Thank you. I am looking forward to future improvements.

Just in case, let me I describe my use case scenario. It is, I believe, the same as for many other PowerShell users. Yes, it is use of System.Data.SQLite from PowerShell scripts. The application in this case is PowerShell.exe and putting something to its directory is not a good idea, if this is possible at all. Thus, System.Data.SQLite.dll and its interop DLLs are somewhere else. It is "always" in my case because PowerShell scripts effectively solve all my database needs. Of course I would like this scenario to be as simple as the current default, i.e. after a few XCOPY steps I do not have to setup or configure anything.

--
Roman

mistachkin added on 2013-12-31 07:45:31:
Fixed (i.e. default changed) on trunk via check-in [73b6826ea6].