@@ -23,6 +23,9 @@ namespace Microsoft.Data.Sqlite
2323    /// <seealso href="https://docs.microsoft.com/dotnet/standard/data/sqlite/async">Async Limitations</seealso> 
2424    public  partial  class  SqliteConnection  :  DbConnection 
2525    { 
26+         private  static readonly  bool  UseOldBehavior35715  = 
27+             AppContext . TryGetSwitch ( "Microsoft.EntityFrameworkCore.Issue35715" ,  out  var  enabled35715 )  &&  enabled35715 ; 
28+ 
2629        internal  const  string  MainDatabaseName  =  "main" ; 
2730
2831        private  const  int  SQLITE_WIN32_DATA_DIRECTORY_TYPE  =  1 ; 
@@ -48,6 +51,8 @@ public partial class SqliteConnection : DbConnection
4851        private  static readonly  StateChangeEventArgs  _fromClosedToOpenEventArgs  =  new  StateChangeEventArgs ( ConnectionState . Closed ,  ConnectionState . Open ) ; 
4952        private  static readonly  StateChangeEventArgs  _fromOpenToClosedEventArgs  =  new  StateChangeEventArgs ( ConnectionState . Open ,  ConnectionState . Closed ) ; 
5053
54+         private  static string [ ] ?  NativeDllSearchDirectories ; 
55+ 
5156        static SqliteConnection ( ) 
5257        { 
5358            Type . GetType ( "SQLitePCL.Batteries_V2, SQLitePCLRaw.batteries_v2" ) 
@@ -624,11 +629,82 @@ public virtual void LoadExtension(string file, string? proc = null)
624629
625630        private  void  LoadExtensionCore ( string  file ,  string ?  proc ) 
626631        { 
627-             var  rc  =  sqlite3_load_extension ( Handle ,  utf8z . FromString ( file ) ,  utf8z . FromString ( proc ) ,  out  var  errmsg ) ; 
628-             if  ( rc  !=  SQLITE_OK ) 
632+             if  ( UseOldBehavior35715 ) 
633+             { 
634+                 var  rc  =  sqlite3_load_extension ( Handle ,  utf8z . FromString ( file ) ,  utf8z . FromString ( proc ) ,  out  var  errmsg ) ; 
635+                 if  ( rc  !=  SQLITE_OK ) 
636+                 { 
637+                     throw  new  SqliteException ( Resources . SqliteNativeError ( rc ,  errmsg . utf8_to_string ( ) ) ,  rc ,  rc ) ; 
638+                 } 
639+             } 
640+             else 
641+             { 
642+                 SqliteException ?  firstException  =  null ; 
643+                 foreach  ( var  path  in  GetLoadExtensionPaths ( file ) ) 
644+                 { 
645+                     var  rc  =  sqlite3_load_extension ( Handle ,  utf8z . FromString ( path ) ,  utf8z . FromString ( proc ) ,  out  var  errmsg ) ; 
646+                     if  ( rc  ==  SQLITE_OK ) 
647+                     { 
648+                         return ; 
649+                     } 
650+ 
651+                     if  ( firstException  ==  null ) 
652+                     { 
653+                         // We store the first exception so that error message looks more obvious if file appears in there 
654+                         firstException  =  new  SqliteException ( Resources . SqliteNativeError ( rc ,  errmsg . utf8_to_string ( ) ) ,  rc ,  rc ) ; 
655+                     } 
656+                 } 
657+ 
658+                 if  ( firstException  !=  null ) 
659+                 { 
660+                     throw  firstException ; 
661+                 } 
662+             } 
663+         } 
664+ 
665+         private  static IEnumerable < string >  GetLoadExtensionPaths ( string  file ) 
666+         { 
667+             // we always try original input first 
668+             yield  return  file ; 
669+ 
670+             string ?  dirName  =  Path . GetDirectoryName ( file ) ; 
671+ 
672+             // we don't try to guess directories for user, if they pass a path either absolute or relative - they're on their own 
673+             if  ( ! string . IsNullOrEmpty ( dirName ) ) 
629674            { 
630-                 throw   new   SqliteException ( Resources . SqliteNativeError ( rc ,   errmsg . utf8_to_string ( ) ) ,   rc ,   rc ) ; 
675+                 yield   break ; 
631676            } 
677+ 
678+             bool  shouldTryAddingLibPrefix  =  ! file . StartsWith ( "lib" ,  StringComparison . Ordinal )  &&  ! RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ; 
679+ 
680+             if  ( shouldTryAddingLibPrefix ) 
681+             { 
682+                 yield  return  $ "lib{ file } "; 
683+             } 
684+ 
685+             NativeDllSearchDirectories  ??=  GetNativeDllSearchDirectories ( ) ; 
686+ 
687+             foreach  ( string  dir  in  NativeDllSearchDirectories ) 
688+             { 
689+                 yield  return  Path . Combine ( dir ,  file ) ; 
690+ 
691+                 if  ( shouldTryAddingLibPrefix ) 
692+                 { 
693+                     yield  return  Path . Combine ( dir ,  $ "lib{ file } ") ; 
694+                 } 
695+             } 
696+         } 
697+ 
698+         private  static string [ ]  GetNativeDllSearchDirectories ( ) 
699+         { 
700+             string ?  searchDirs  =  AppContext . GetData ( "NATIVE_DLL_SEARCH_DIRECTORIES" )  as  string ; 
701+ 
702+             if  ( string . IsNullOrEmpty ( searchDirs ) ) 
703+             { 
704+                 return  [ ] ; 
705+             } 
706+ 
707+             return  searchDirs ! . Split ( [  Path . PathSeparator  ] ,  StringSplitOptions . RemoveEmptyEntries ) ; 
632708        } 
633709
634710        /// <summary> 
0 commit comments