Download LINQPad 8

LINQPad 8 supports C# 12 and targets .NET 8, .NET 7 and .NET 6 (with limited support for .NET 5 and .NET Core 3.1).
(For .NET Framework support, run LINQPad 5 side-by-side.)

Download LINQPad 8 - RTM

Download LINQPad 8 - Latest Beta

See beta release notes

X64 + X86 + ARM64 (Windows)

Release Notes

To enable paid features of LINQPad 8, you will need to upgrade your license to Version 8 if you purchased an older major version (such as version 6 or version 5). A LINQPad 8 license also works for all previous versions of LINQPad.

LINQPad 8.1

Security Updates

  • The LINQ-to-SQL driver now uses System.Data.SqlClient 4.8.6, in response to CVE 2024 0056.
  • In response to the plethera of recent CVEs in Microsoft.Data.SqlClient and its dependencies, the EF Core driver includes a new option to promote package dependencies to fix security vulnerabilities - without having to wait for the EF Core team to address the issue. The database of dependency patches is contained within a text file that is maintained by LINQPad and can be patched without requiring a LINQPad version update. This feature is enabled by default - you can disable it via a checkbox in the EF Core connection properties dialog.
  • NuGet vulnerability warning messages are now grouped and displayed compactly, in an expandable details element.

New Features

  • LINQPad's interactive authentication dialog now includes an opt-in checkbox to securely persist access tokens to disk using the Microsoft.Identity.Client.Extensions.Msal library. Enabling this option means that you can avoid re-authenticating when restarting LINQPad (or when running multiple LINQPad instances) and is useful when the operating system's Single Sign-On is unable to perform the job. You can list and delete tokens via options on the Help menu and the connection context menu, or by navigating to the %localappdata%\LINQPad\MSALCache folder.
  • There's now a checkbox option in Edit | Preferences > Results to use a fixed-pitched font when dumping text.
  • LINQPad's EF Core driver now supports HierarchyId columns with SQL Server. To enable, tick the checkbox in the connection properties dialog.
  • LINQPad now supports F# 8.
  • Autocompletion is now less intrusive when working with tuples.
  • There's now a guard to prevent accidentally switching between query languages via a hotkey.
  • Util.Cache now has an overload to accept a time-to-live, after which the cache entry expires. There's also new a Util.CacheAsync method to cache tasks. CacheAsync is identical to Cache except that it includes logic to ensure that faulted tasks are not cached.
  • When closing queries (or LINQPad itself), LINQPad now allocates 750ms to queries that are monitoring QueryCancelToken to complete any cleanup before killing their processes.
  • The undo buffer size for the editor has been enlarged by a factor of 10.
  • The PowerPoint interop method (PowerPoint.ShowSlide) now works with modern versions of PowerPoint.
  • LINQPad is now better at distinguishing SQL Server system objects.
LINQPad 8

New Features - General

  • LINQPad's tab control, toolbar, and menu renderer have been rewritten for better performance, appearance and dark-theme rendering. Icons have been updated for greater consistency with Visual Studio, and are drawn with theme-optimized scalable graphics. Dark theming has also been improved in a number of other areas, including commonly used dialogs, data grids and autocompletion tooltips.
  • LINQPad's toolbar includes a new dropdown to set the transaction isolation level for queries that use LINQ-to-SQL or EF Core connections. This can function with or without a transaction, and works by automatically issuing a SET TRANSACTION ISOLATION LEVEL command immediately after LINQ-to-SQL or EF Core opens a connection. (Working without a transaction in the read-committed or snapshot isolation levels is useful for querying a database without blocking updates.) You can also set a per-connection default by right-clicking the combo, and set/override the isolation level programmatically via the Util.TransactionIsolationLevel property.
  • LINQPad has a new toolbar button to automatically generate a description when dumping. You can also access this behavior programmatically by calling DumpTell instead of Dump. To make this feature enabled by default for new queries, right-click the button and choose the option on the context menu. When active, you can still override the description by calling Dump("heading") - or Dump("") for no heading.
  • You can now render Avalonia controls directly inside LINQPad, just by dumping them. For samples, press Ctrl+F1 and type Avalonia.
  • LINQPad now restores both modified and unmodified queries after closing and shelving. There's also now an Always Shelve button directly on the Exit dialog.
  • There's a new item on the File menu to restart LINQPad (shortcut Ctrl+Alt+Shift+Delete). This will restore all queries that were open.
  • You can now press Ctrl+Plus to navigate forward in the editor. Ctrl+Shift+Minus also works, if used after a Navigate Back.
  • LINQPad's interactive authentication engine now uses a custom UI host for better reliability and compatibility with the latest authentication schemes. It can also now propagate tokens across multiple process boundaries, so a query that you execute via Util.Run will not re-authenticate unnecessarily.
  • LINQPad now includes a self-diagnostic tool for monitoring latency and blockages on the UI thread. Should you experience an issue, go to Help | Start Internal Profiling - this will generate a report that you can send to tech support. There's also a new Process Monitor to monitor the memory and CPU usage of each query, as well as the host process.
  • Util.HtmlHead.AddScript now supports a type attribute. There's also now a Util.HtmlHead.AddRawHtml method for additional flexibility.
  • The EF Core driver supports DateOnly/TimeOnly type mappings with EF Core 8+. You can switch this feature on or off via a checkbox in the connection dialog.
  • LINQPad's EF Core connection dialog lets you specify compatibility level for SQL Server connections, to mitigate the breaking change in EF Core 8.
  • When you try to save a read-only file, LINQPad now presents a dialog with options to save to a different file, or overwrite anyway (after a second confirmation). You can also now make a query read-only or writable via context menu options on the query tab.
  • LINQPad 8 always loads queries into noncollectible Assembly Load Contexts, to maximize compatibility with third-party libraries.
  • Autocompletion's member info tooltips now show exception tags.

New Features - Excel Interop

LINQPad has a new Excel export engine that generates native .xlsx content instead of relying on HTML or CSV. This ensures reliable handling of DateTimes and extended Unicode characters, the preservation of leading zeros in string data (such as phone numbers), and allows for the generation of multi-sheet workbooks. It also works in environments that block Excel's HTML import feature for security reasons.

You can access the Excel export engine interactively in any of the following ways:

  • (new) by clicking the ellipses on a table in the Results view
  • via the Export menu option on the Results toolbar
  • by right-clicking a Data Grid

You can also export data programmatically by calling the .ToSpreadsheet extension method, followed by Open or Save:

customers.ToSpreadsheet().Open();

salesQuery.ToSpreadsheet().Save ("salesQuery.xlsx");

The Save method does not require Excel to be installed on the machine.

You can include multiple sheets in a single workbook by calling the fluent .AddSheet method:

customersQuery
    .ToSpreadsheet ("Customers")
    .AddSheet (ordersQuery, "Orders")
    .AddSheet (profitsQuery, "Profit and Loss")
    .Save (@"c:\temp\export.xlsx")
    .Open();

Spreadsheets can also be populated manually:

var sheet = new Worksheet        // Worksheet is in the LINQPad.Spreadsheet namespace.
{
    [1, 1] = "Revenue",
    [1, 2] = "Expenses",
    [1, 4] = "Profit",

    [2, 1] = 150230,
    [2, 2] = 25010,
    [2, 4] = new Cell { Formula = "B1-B2" }
};

sheet.Open();
// or sheet.Save ("filepath");

This is much faster than using COM interop to populate a spreadsheet, because no round-tripping takes place.

For more samples, press Ctrl+F1 and type Excel.

Architectural Changes

  • LINQPad 8's query and daemon process launcher has been redesigned to use the startup executable, with a redirection taking place within a custom CLR host. This makes LINQPad friendly to environments that block executables that reside outside the Program Files folder, as well as reducing the chance of triggering antivirus software into blocking or slowing their startup. This also means that to whitelist the LINQPad process, you now need to specify only the startup executable.
  • LINQPad no longer uses the soon-to-be-removed .NET binary serialization engine in any capacity; instead, it now uses a custom-written replacement that recognizes the same attributes. This means that Util.Cache still works to cache data between executions when types get recompiled between executions, as long as you apply the [Serializable] attribute when requested.
  • LINQPad's host and command-line runner now targets .NET 6+. LINQPad.Runtime, however, still targets .NET Core 3.1, so that you can interactively run code under .NET Core 3.1 and .NET 5 (which some restrictions, described in the following section). Dependencies of LINQPad.Runtime that require .NET 6+ have been moved to a separate internal library that resolves automatically via an internal dependency injection mechanism.
  • LINQPad has a new assembly resolution mechanism for the host and command-line runner that has greater authority when versioning discrepancies occur between the the host and framework libraries (and their transitive dependencies). This has allowed for a refresh of LINQPad's internal libraries, while still supporting a range of .NET versions.

Deployment

LINQPad 8 requires at least one of the following runtimes:

  • .NET 8 (Desktop)
  • .NET 7 (Desktop)
  • .NET 6 (Desktop)

If none of these have been installed, LINQPad will bootstrap the installation of .NET 8. If multiple runtimes have been installed, you can choose which to use on a per-query basis via a dropdown in the toolbar. (You can also set a global default in Edit | Preferences.)

LINQPad 8 also lets you test queries under .NET 5 and .NET Core 3.1, with the following limitations:
  • .NET 8/7/6 must also be installed.
  • X64 disassembly and C# 1.0 decompilation is unavailable for the obsolete runtimes.
  • Util.Run and LPRun.exe do not work with the obsolete runtimes.

Should you need full support for .NET 5 or .NET Core 3.1, you can run LINQPad 7 side-by-side.

The xcopy-deployable version of LINQPad 8 ships with the following launchers:

LINQPad8-x64.exe    // for X64
LINQPad8-x86.exe    // for X86 - choose this if you need to reference native 32-bit DLLs
LINQPad8-arm64.exe  // for ARM64 machines such as Surface Pro X

It is recommended that you rename/copy the launcher that corresponds to your native platform to LINQPad8.exe.

LINQPad's launchers are custom CLR hosts. This allows them to bind the host to the optimum .NET version, and bootstrap the installation of .NET if no suitable version has been installed.

The command-line launchers are as follows:

LPRun8-x64.exe    // X64
LPRun8-x86.exe    // X86
LPRun8-arm64.exe  // ARM64

It is recommended that you rename/copy the launcher that corresponds to your native platform to LPRun8.exe (the installer does this for you automatically).

Custom CLR hosts and include logic on the unmanaged side to determine which .NET version to spin up. Instead of looking for a .runtimeconfig.json file, the command-line launchers locate and examine the .linq query that you want to run. If you chose a specific .NET version in the toolbar when you wrote the query, this will have been saved to the .linq file, and this choice will be honored. Otherwise the launcher parses the user-preferences file for your default framework choice.

You can also specify/override the .NET version with LPRun8's -fx switch:

LPRun8 -fx=8.0 (query-to-run)   // Run query under .NET 8.0
LPRun8 -fx=7.0 (query-to-run)   // Run query under .NET 7.0
LPRun8 -fx=6.0 (query-to-run)   // Run query under .NET 6.0

EF Core 8.0

LINQPad 8 supports Entity Framework Core 8.0 (as well as older versions). LINQPad's EF Core driver understands the compatibility matrix between versions/subversions of .NET and EF Core, and if necessary, will switch your query to the closest compatible .NET version (with a warning).

Licensing

To enable the Premium features of LINQPad 8, you will need to upgrade your license to Version 8 (unless you purchased recently.) A LINQPad 8 license works for all older versions of LINQPad, too.

Running LINQPad versions side-by-side

For .NET Framework support, you can continue to run LINQPad 5 side-by-side with LINQPad 8.

Here are some tips to help you with sharing queries between LINQPad 5 and LINQPad 8:

  • Any .NET Framework assembly references are ignored in LINQPad 8.
  • Other assembly references may cause difficulties unless they are to .NET Standard libraries. NuGet package references are the best option.
  • For conditional compilation, the NETCORE symbol is defined in LINQPad 8 but not LINQPad 5.
  • My Extensions is separate for LINQPad 5 and 8, so each can have different implementations and dependencies. As long as you provide textually similar methods in both, queries will work with both.

LINQPad 8 - Latest Beta

What's new

New Features - Dev Drive Support

You can now speed up LINQPad by creating a Windows Dev Drive. Windows Dev Drive improves performance for developer workloads by instructing Windows Defender to virus-scan files on that drive asynchronously (or not at all, if you choose).

Note that you don't need to move your .linq files onto a Dev Drive to benefit - merely creating a Dev Drive will result in LINQPad writing performance-critical compilation output to that drive, mitigating most of the virus-scanning latency. You can check whether LINQPad is using your Dev Drive in Help | About, or by running the Antivirus Performance Test on the Help menu. Dev Drive is used by both the LINQPad GUI and the command-line runner (LPRun).

Compilation output and other temporary files end up in a hidden folder on your Dev Drive called \.linqpad.tmp\user. LINQPad sets the permissions on the user subfolder such that that other non-admin users have delete-only access.

Should you wish to disable this feature, there's an option in Edit | Preference > Advanced to prevent LINQPad from automatically detecting and using Dev Drive.

New Features - General

  • The connection dropdown in the toolbar is now faster when there are a large number of items.
  • The web proxy settings dialog (Edit | Preferences > Web Proxy) now has a checkbox to enable the proxy in interactive authentication scenarios such as Azure Entra.
  • Informational popups that appear at startup can now be suppressed via a checkbox.
  • Cyclic references now take up less space when rendered.

Fixes

  • Queries returning Task<int> now propagate the return value to the process exit code when called via LPRun.
  • A potential bug when Windows high-contrast dark themes are enabled has been fixed.
  • The Util.ProgressBar class can now be repeatedly shown and hidden.
  • URIs with anchors in F# queries now parse correctly.

Security Patches

  • LINQPad 8.2.4 uses NuGet.Packaging 6.7.1 to work around CVE-2024-0057.
Download LINQPad 8 Beta

Current beta version: 8.2.4

LINQPad 8 betas automatically update when a newer beta is released.

(Scroll up for release versions)