Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC for ARM64 support of LocalDB #1952

Conversation

Matteo-T
Copy link

@DavoudEshtehari / @cheenamalhotra / @David-Engel - FYI, this the "Proof of Concept" I've been toying with in the last couple of days.

The logic is as follows:

  • Try to existing logic, which is to load the SqlLocalDB DLL
  • If that fails (typically because there is an architecture mismatch, like running the driver under ARM64 and trying to load SqlUserInstance.dll that is AMD64):
    • lookup the registry and get the latest SqlLocalDb.exe installer on the machine
    • spawn SqlLocalDB.exe s <instancename> (to make sure the instance is started) - it's a no-op if it is already running, I believe
    • spawn SqlLocalDB.exe i <instancename> to get the connection string, i.e. the named pipe to use - assumption: SqlLocalDB always exposed named pipes
    • use that connection string

Here's my test app (built for net7.0):

using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Data.SqlClient;
class Program
{
    // Requires SqlLocalDB installed on the machine
    // Ideally on ARM64
    // 
    static string connectionString = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=true";

    static void Main(string[] args)
    {
        bool UseManagedNetworkingOnWindows = args.Length == 0;

        AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows", UseManagedNetworkingOnWindows);

        Console.WriteLine("Run");
        Console.WriteLine($" dotnet-trace collect --providers \"Microsoft.Data.SqlClient.EventSource\" --process-id {Process.GetCurrentProcess().Id}");
        Console.WriteLine("then press <ENTER>");
        Console.ReadLine();

        Console.WriteLine($"UseManagedNetworkingOnWindows={UseManagedNetworkingOnWindows}");
        Console.WriteLine($"Environment.Is64BitOperatingSystem={Environment.Is64BitOperatingSystem}");
        Console.WriteLine($"Environment.Is64BitProcess={Environment.Is64BitProcess}");
        Console.WriteLine($"GetSystemVersion()={RuntimeEnvironment.GetSystemVersion()}");
        Console.WriteLine($"Environment.OSVersion.VersionString={Environment.OSVersion.VersionString}");
        Console.WriteLine($"RuntimeInformation.OSArchitecture={RuntimeInformation.OSArchitecture}");
        Console.WriteLine($"RuntimeInformation.RuntimeIdentifier={RuntimeInformation.RuntimeIdentifier}");
        Console.WriteLine($"RuntimeInformation.ProcessArchitecture={RuntimeInformation.ProcessArchitecture}");
        Console.WriteLine();

        var query = "SELECT @@VERSION, @@SERVERNAME";

        Console.WriteLine($"Connection string: {connectionString}");
        Console.WriteLine($"Query: {query}");

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            var cmd = new SqlCommand(@"SELECT @@VERSION, @@SERVERNAME", connection);
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    Console.WriteLine(reader.GetString(0));
                    Console.WriteLine(reader.GetString(1));
                }
            }
        }
    }
}

It's output looks like this on my ARM64 box:

Run
 dotnet-trace collect --providers "Microsoft.Data.SqlClient.EventSource" --process-id 21568
then press <ENTER>

UseManagedNetworkingOnWindows=True
Environment.Is64BitOperatingSystem=True
Environment.Is64BitProcess=True
GetSystemVersion()=v4.0.30319
Environment.OSVersion.VersionString=Microsoft Windows NT 10.0.22621.0
RuntimeInformation.OSArchitecture=Arm64
RuntimeInformation.RuntimeIdentifier=win10-arm64
RuntimeInformation.ProcessArchitecture=Arm64

Connection string: Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=true
Query: SELECT @@VERSION, @@SERVERNAME
Microsoft SQL Server 2022 (RTM-CU1) (KB5022375) - 16.0.4003.1 (X64)
        Jan 27 2023 16:51:31
        Copyright (C) 2022 Microsoft Corporation
        Express Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 22621: ) (VM)

SQLToolsArm-2\LOCALDB#5E67B8B5

@@ -103,6 +233,9 @@ internal static string MapLocalDBErrorStateToErrorMessage(LocalDBErrorState erro
/// </summary>
private bool LoadUserInstanceDll()
{
_sqlUserInstanceLibraryHandle = null;
throw new Exception();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not meant to be part of the change. I may have been playing around with it on my AMD64 dev box, so I wanted to make it fail artificially. Oops...

@Matteo-T
Copy link
Author

Any takers? Good? Bad? Horrible? :)


// TODO: Are named pipes the only option for SqlLocaLDB?
// TODO: Probably sensitive to move out of this method to avoid compiling it all the time
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("(np:.+)\r", System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.CultureInvariant);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a timeout

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup - keep in mind this is very crude PoC.


var lines = alllines.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

// TODO: Are named pipes the only option for SqlLocaLDB?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, LocalDB only uses named pipes (no networking)

// the connection string we are looking for!
foreach (var line in lines)
{
var foo = regex.Match(line);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var match

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely!

@JRahnama
Copy link
Member

Closing as this is a POC and work has been carried forward in a different PR.

@JRahnama JRahnama closed this Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants