LINQPad 8 for Windows

LINQPad 8 supports C# 13 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)

LINQPad 8 for macOS

Click here to download LINQPad 8 for macOS.

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.6

General

  • LINQPad now supports .NET 9 RTM.
  • LINQPad's samples now include 'What's new for C# 13.'
  • LINQPad can now execute .cs files that define a file-scoped namespace.

Fixes

  • A regression in the how the debugger's stack trace handles recursive methods has been fixed.
  • The HTML Image control in LINQPad.Controls is now more flexible in how it handles attributes and styles when a Util.ScaleMode is specified.
  • A bug in LINQPad's EF Core driver that prevented MySQL version 3.x from working has been fixed.
  • The LINQ-to-SQL driver now correctly lists stored procedures that use table types.
LINQPad 8.5

Security Updates

  • LINQPad now uses System.Text.Json 8.0.4, in response to CVE-2024-30105.

General

  • The NuGet package manager now supports Azure DevOps and OAuth interactive authentication modes.
  • Data Context Drivers can now force-enable the Query Properties option to copy local referenced files into the local output folder by overriding the AlwaysCopyLocal method.
  • There's now support for C# 13 features to revision 4.10.0, if language preview mode is enabled in Edit | Preferences > Query.
  • You can now specify a redirection URI when calling Util.MSAL.AcquireTokenAsync to satisfy server requirements. (Because the output of this method is a token, the URI is not actually followed).
  • You can disable 'Go to Definition' on Ctrl+Click in Edit | Preferences > Advanced.

Fixes

  • Autocompletion now works correctly on the right-hand side of assignment expressions in object initializers.
  • A regression in the EF Core driver causing populated EFCore associations to render incorrectly has been fixed.
LINQPad 8.4

Security Updates

  • LINQPad now uses Azure.Identity 1.11.4, in response to CVE-2024-35255.

New Features - Dump

  • Util.Dif can now detect inserted and removed items in lists of complex objects.
  • There's a new DumpOptions class that can be used for specifying parameters when calling Dump. This supports additional options such as MaxRows (to increase or decrease the row limit in HTML mode from the default of 1000), and FormatStrings, which allows you to specify format strings for numeric and date/time types on a per-Dump basis. (This overrides any global defaults specified in Edit | Preferences.)

    You can also set defaults for a query via the static DumpOptions.Default property (or Util.DumpDefaults):
    DumpOptions.Default.MaxRows = 20000;
    DumpOptions.Default.FormatStrings.DateTime = "yyyy-MM-dd";
    DumpOptions.Default.FormatStrings.IntegralNumber = 
        DumpFormatStrings.Constants.IntegralNumberWithGroupSeparator;
    
    Enumerable.Range (0, 20000).Select (days => new { days, Date = DateTime.Now.AddDays (days) }).Dump();
    
  • You can now force the expansion of objects that implement IFormattable (such as DateTime), either by specifying a depth when calling Dump, or with DumpOptions.ForceExpansion.
  • ValueTask is now treated like Task when dumped.
  • There's a new DumpAsync method for IAsyncEnumerables. This behaves just like Dump except that it returns an awaitable Task that completes when the Dump has completed. This allows you to ensure that execution does not proceed until the sequence has been fully awaited.
  • Exceptions stack traces now include hyperlinks when dumped.

New Features - EF Core Support

  • Many-to-many relationships in custom EFCore models are now shown in the Schema Explorer.
  • Populated EFCore associations are now rendered automatically when dumped.
  • The dialog for custom EF Core connections now lets you pick DbContext types that are marked as internal, if the defining assembly includes the [InternalsVisibleTo("LINQPadQuery")] attribute.
  • When defining custom DbContext classes for use with LINQPad, you can now include additional optional parameters in the constructor that accepts a DbContextOptions parameter. For example:
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options, string extraData = null)
            : base(options)
        {
            ...
        }
        ...
    
    LINQPad will pass in the default value for any optional parameters (null in this example).

New Features - General

  • You can now Ctrl+Click on symbols to navigate to their definition (or reflect in ILSpy).
  • When LINQPad displays parameter lists for overloaded methods, it now does a better job of jumping to an overload compatible with what's been typed so far.
  • Util.Run now lets you specify file paths relative to where the calling query was saved (matching the behavior of #load). As before, file paths can also be relative to Environment.CurrentDirectory or the My Queries folder. You can also now omit the .linq file extension.
  • LPRun.exe can now resolve paths relative to the My Queries folder, and lets you omit the .linq file extension.
  • LINQPad's editor now supports .tsv files (tab-separated-values).
  • The contents of Span and Memory types now show in the debugger.

Fixes

  • A thread-safety issue that could cause duplicate headings when dumping from multiple threads concurrently has been fixed.
  • A bug in Util.Cache's serializer that could cause it to ignore private fields has been fixed.
  • LINQPad's now take steps to ensure that the resolution of a .NET assembly overridden by a newer version from NuGet is not upset by the presence of a downstream .NET assembly that's not overridden.
  • Tables named 'file' and 'system' no longer cause an error with the LINQ-to-SQL or EF Core drivers, regardless of property capitalization settings.
  • LINQPad now correctly processes databases with non-unique foreign key constraint names, as long as each name is unique per schema.
LINQPad 8.3

Security Updates

  • LINQPad's EF Core driver now forces the use of Azure.Identity 1.11.0 when the SQL Server provider is selected, to work around CVE-2024-29992.

New Features

  • LINQPad 8 now supports the .NET 9 preview and the EF Core 9 preview.
  • NuGet packages that contain only satellite assemblies are now supported in LINQPad.
  • ILSpy has been updated to version 8.2.
  • Dump in Data Grid mode now supports the include and exclude options to include or exclude specific properties or fields.
  • When inside a generic method or class, the debugger's Threads and Call Stack windows now show the type parameters in the code location.
  • Util.ToHtmlString and Util.CreateXhtmlWriter now emit HTML that's more consistent with what's rendered in the results window.
  • LINQPad now automatically applies XML comments on interface members to their implementations, if no other comment is available.
  • The maximum HTML content length for the results window has been increased.

Fixes

  • An intermittent problem that could cause duplication when appending data to a DumpContainer has been fixed.
  • A scenario in which the asynchronous use of Util.Cache could hang instead of throwing an exception has been fixed.
  • You can now reliably copy and paste cells from LINQPad-generated Excel spreadsheets without error.
  • TabControl keyboard navigation shortcuts now work correctly in the Query Properties dialog.
  • Progress bars generated with Util.ProgressBar are now visible immediately after being dumped.
  • A parsing bug that could prevent the entry of negative numbers when editing tables in Data Grid mode has been fixed.
  • When an subclass hides a base class member with C#'s new keyword, LINQPad's Dump engine now ensures that the subclass's member takes priority.
LINQPad 8.2

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.
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 run queries under .NET 5 and .NET Core 3.1, with the following limitations:

  • .NET 9, 8, 7 or 6 must also be installed.
  • X64 disassembly and C# 1.0 decompilation is unavailable.
  • Util.Run and LPRun.exe do not work under .NET 5 or .NET Core 3.1.

Should you need these features, 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

General

  • LINQPad now supports the latest C# preview features, including the new field keyword.

Fixes

  • A regression in the ARM64 build of LINQPad that broke ILSpy integration has been fixed.
Download LINQPad 8 Beta Update Stream

Current beta version: 8.7.2

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

(Scroll up for release versions)