Home

DirectoryNotFoundException with custom driver: LinqPad fails to create temporary data context files?

edited March 2021

Hello! I have a custom data context driver that worked quite well with LinqPad 5. Porting it to LinqPad 6 was quite straight-forward, but I'm facing an issue when I try to use it. Steps I take:
1. I install the driver from an lpx6 file.
2. I create a connection through the driver. This works fine (the connection window appears, etc).
3. I create a query and set it to use my newly created connection.
4. A LINQPad error window appears:

System.IO.DirectoryNotFoundException
Could not find a part of the path '{AppData}\Local\Temp\LINQPad6_ccicsknp\dc-2\ {some_library}.dll'

Now if I browse to '{AppData}\Local\Temp\LINQPad6\' I don't even see a folder named _ccicsknp, just one called _zfckfchs which itself contains a folder named dc-1, which in turns contains a file {some_other_library}.dll

If I manually create the folder and copy the file from {AppData}\Local\LINQPad\Drivers\DataContext\NetCore{My.Driver}{some_library}.dll to the path '{AppData}\Local\Temp\LINQPad6_ccicsknp\dc-2\ {some_library}.dll', then my query start to work.

Am I doing something wrong?

Comments

  • Are you returning that assembly in the GetAssembliesToAdd method? If so, can you post the code in that method?

  • Thanks for your reply!
    Yes, that assembly is returned by GetAssembliesToAdd. The code is illustrated below (I redacted the filenames a bit, but I have excluded typos to be the culprit (the same code works on LinqPad 5):

    public override IEnumerable<string> GetAssembliesToAdd(IConnectionInfo cxInfo)
    {
        return new[] 
        { 
            "Utils.dll", 
            "Data.Conversion.dll", 
            "Telemetry.dll" // the one that causes the error
        };
    }
    

    I also tried the following, to no avail (same error for same assembly).

    public override IEnumerable<string> GetAssembliesToAdd(IConnectionInfo cxInfo)
    {
        return new[] 
        { 
            "*"
        };
    }
    

    A note about the assemblies: they all target netstandard2.0, and have the following dependencies:

    • Telemetry -> Utils
    • Data.Conversion -> Utils
    • Data.Conversion -> Telemetry

    The three of them also have NuGet dependencies but these are well defined in a deps.json file in the package.

  • edited March 2021

    Are you absolutely sure that you're specifying a simple filename and not an absolute path? And if so, can you resubmit an error report with GetAssembliesToAdd returning new[] { "*" }?

  • I guarantee that the method returns simple filenames. I just made a new version with new[] { "*" } and submitted an error report. Let me know if I can provide more details. And thanks for your help!

  • You'll need to send me your project. The data I'm seeing doesn't make any sense.

  • edited March 2021

    Sure. Would the lpx6 file be enough?

  • edited March 2021

    I just now revisited my project and realized one of the NuGet dependencies for the .NET Core driver is a package that has only netframework4.6 support, not netstandard2.0. The package in question is https://www.nuget.org/packages/OrcaMDF.Core/1.0.0/ but the odd part is that it is not a dependency of the DLL that appeared in the error message. Rather, it is a dependency of another DLL that depends on that DLL.

    If I remove this package from the driver dependencies, the driver works correctly (but of course queries will throw a reflection exception if I attempt to use any method that depends on the now missing NuGet package).

  • I spoke too soon. I had manually fixed the one query I was testing with. The problem persists when I create a new query.

  • Send me the .lpx6 for now - along a step-by-step repro with any necessary supporting files.

  • edited March 2021

    The problem is that you are hard-coding the path to the user's static data context assembly in the connection dialog as follows:

    customTypeInfo.CustomAssemblyPath = typeof (Telemetry.Analysis.DataContext).Assembly.Location;
    

    The path to assembly will be a temporary copy that LINQPad creates for your data context operations. Even if LINQPad didn't shadow the assembly, this would still be unreliable because it could change depending on where the driver was installed. Remember that the assembly path will end up in your .linq files which can be shared with others.

    To help with this scenario - where the static data context is supplied by the driver author rather than the end user - I'll allow CustomAssemblyPath to be populated with a simple filename (no path) in the next LINQPad beta. This will then resolve to any type in your set of referenced assemblies. In the meantime, you can solve this by creating a dynamic data context driver. This is simple to do because your generated class doesn't define any new types or properties. All it must do is subclass your hard-coded base type:

    public override List<ExplorerItem> GetSchemaAndBuildAssembly (IConnectionInfo cxInfo, AssemblyName assemblyToBuild,
                                                                  ref string nameSpace, ref string typeName)
    {
        string[] refPaths = GetCoreFxReferenceAssemblies().Union (new[] {
            typeof (Telemetry.Analysis.DataContext).Assembly.Location,
            // Anything other dependencies required for compilation...
        }).ToArray();
    
        string source = @$"namespace {nameSpace}
    {{
        public class {typeName} : Telemetry.Analysis.DataContext {{ }}
    }}";
    
        var result = CompileSource (new CompilationInput
        {
            SourceCode = new[] { source },
            FilePathsToReference = refPaths,
            OutputPath = assemblyToBuild.CodeBase
        });
    
        return new ExplorerItem [0].ToList();
    }
    
  • Thanks a lot for looking into it and for your reply. I tried the workaround with the dynamic driver but I'm getting an error
    'object' does not contain a constructor that takes 1 arguments
    when trying to run the query.

    Could it be related to your comment:
    // Anything other dependencies required for compilation...
    what do I need to put there? Assemblies on which Telemetry.Analysis.DataContext depends? Also NuGet dependencies?

  • Follow-up to fully resolve this: I never managed to make the dynamic driver work, however the "relative filename CustomAssemblyPath" trick is now working as of 6.13.13. Thanks for the help!

Sign In or Register to comment.