Developing .NET on ARM: Issue 1 – LocalDB/SQL Server

I recently bought a computer with an ARM processor and started exploring its potential for .NET development. Right off the bat, I encountered some issues related to LocalDB and SQL Server. In this article, I’ll explain how I mitigated these problems using Docker and a specialized version of SQL Server designed for resource-constrained environments: Azure SQL Edge.

LocalDB on ARM problem

Currently, there is no support for LocalDB or SQL Server, whether the full or express version, on ARM in Windows. When I tried running EF Core with a migration, I received an error message stating that it was unable to load SQLUserInstance.dll.

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 56 – Unable to load the SQLUserInstance.dll from the location specified in the registry. Verify that the Local Database Runtime feature of SQL Server Express is properly installed.)

My current setup

  • IDE: Visual Studio 2022 (Web Development Workload installed)
  • Entity Framework Core: Version 9 installed globally.

Initial Attempt with LocalDB

This is the connection string for a basic .NET project using LocalDB:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;MultipleActiveResultSets=true"
  }  
}

Solution: Run SQL Server on Linux via Docker

Azure SQL Edge is a streamlined version of SQL Server focused on edge computing and IoT. Although the documentation states that Azure SQL Edge no longer supports arm64 platforms, inspecting the image reveals that it is multi-platform.

Since it is multi-platform, I can run this image without the performance issues that would occur if the container were running in emulation mode.

To inspect the Docker image run docker manifest inspect mcr.microsoft.com/azure-sql-edge.

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 2634,
         "digest": "sha256:3544cf1c6847c5cb60e071638c48b1b45d05a64eb2d88d0f83d44b397f40b186",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1164,
         "digest": "sha256:94fb68ba50aa0abbd60b1e3efcf1686c6b03b90ed51e67fb79d71f4446f7a63a",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      }
   ]
}

Setting Up SQL Server with Docker

Prerequisite

Ensure WSL and Docker Desktop are installed on your system.

Step 1: Download the Azure SQL Edge image

Run the following command to pull the image:

docker pull mcr.microsoft.com/azure-sql-edge

Step 2: Start the Container

You can start the container with a simple docker run command, but I prefer using a Docker Compose file for better configuration management.

Here’s an example docker-compose.yml file:

version: '3.8'
services:
  sqlserver:
    image: mcr.microsoft.com/azure-sql-edge
    container_name: sqlserver
    ports:
      - "1433:1433"
    environment:
      SA_PASSWORD: "YourPassword"
      ACCEPT_EULA: "Y"
    volumes:
      - sql_data:/var/opt/mssql
volumes:
  sql_data:

In the same folder where you saved the docker-compose.yml file, start the container with the command docker-compose up -d in the terminal.

docker-compose up -d

Testing the Connection

Use your preferred tool to test the connection. For example, with SQL Server Management Studio (SSMS):

  • Server Type: Database Engine
  • Server Name: localhost
  • Authentication: SQL Server Authentication
  • Login: sa
  • Password: YourPassword (or the password you set in the Docker Compose file)

If the connection is successful, you’re ready to proceed.

Updating the Connection String

Update your application’s connection string to point to the new database. For example:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost,1433;Database=MyDatabase;User Id=sa;Password=YourPassword;MultipleActiveResultSets=true "
  }
}

Applying Migrations

Run the following command to apply the EF migrations:

dotnet ef database update

Common Error: Certificate Issue

You might encounter an error related to SSL certificates.

A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 – The certificate chain was issued by an authority that is not trusted.)

To resolve this, update the connection string to include TrustServerCertificate=True:

{
"ConnectionStrings": {
    "DefaultConnection": "Server=localhost,1433;Database=MyDatabase;User Id=sa;Password=YourPassword;MultipleActiveResultSets=true;TrustServerCertificate=True"
  }
}

Run the migration again:

dotnet ef database update

Success!

The .NET application is now set up to use a containerized SQL Server database on an ARM processor. While the Azure SQL Edge provides a practical solution for development today, you can use it as a temporary workaround until Microsoft addresses the compatibility issues with SQL Server and LocalDB on ARM platforms.

Comments (0)

Start the conversation!