.NET 10 Release Candidate 1: Follow-up for Entity Framework Core

Microsoft ORM Mapper learns column types Vector and JSON in Microsoft SQL Server 2025. At the same time, there is a first insider version of Visual Studio 2026.

listen Print view
Traffic sign with the inscription .NET

(Image: Pincasso/Shutterstock.com)

9 min. read
By
  • Dr. Holger Schwichtenberg
Contents

According to Microsoft's plan, .NET 10.0 should actually be "feature complete" at the end of the preview phase before the freshly released Release Candidate 1, and the two Release Candidate versions should only serve to improve quality. According to the announcement, this also applies to the runtime environment, SDK, language compiler (C#, F#, Visual Basic .NET), and WPF. However, as in the past, there are also parts of .NET that will deliver significant new functions in Release Candidate 1. This time, it particularly concerns Entity Framework Core and ASP.NET Core as well as MAUI.

.NET 10.0 Release Candidate 1 is available on the .NET download page. As with previous versions, Release Candidate 1 has a go-live license: developers can use the version productively and receive official support from Microsoft. Nevertheless, they still have to expect changes until the release date, which has been announced for November 11, 2025.

.NET 10.0 Release Candidate 1 has the go live label.

Visual Studio 2022 has also been updated from version 17.14.13 to 17.14.14. However, compiling a .NET 10.0 application is only possible if you use 17.14.14 Preview 1.0 or the first preview version of Visual Studio 2026 (aka “18.0.0 Insiders”). In addition to even more AI integration, the 2026 version also offers a new look and feel in Fluent Design with numerous new themes such as Icy Mint, Cool Breeze, Mango Paradise, and Spicy Red.

You can quickly switch between the themes in Visual Studio 2026 in the Tools/Theme menu.

According to a Microsoft blog post, Visual Studio 2026 will also be faster. One detail stands out positively during installation: Visual Studio 2026 asks whether you want to transfer a configuration (workloads, individual components, extensions, and settings) from an existing Visual Studio 2022 installation on the computer or a .vsconfig file (see the following figure). Visual Studio 2022 could already use .vsconfig files during installation, but only when starting the IDE installation via command line (parameter --config).

In contrast to the two 2022 versions, Visual Studio 2026 also offers the installation of the .NET 10.0 SDK as an “Individual Component.” In the older versions, the .NET SDK must be installed manually from the download page.

Visual Studio 2026 offers to take over existing configurations during installation.

As of Release Candidate 1, Entity Framework Core supports the two new column types JSON and VECTOR, which are available in Microsoft SQL Server 2025 (currently in the preview phase and the SQL Azure cloud variant). JSON has already been used by Entity Framework Core to map a list of primitive data types, such as List<int> to a single table column—except in PostgreSQL, which natively handles such sets, or when storing so-called owned types. Previously, however, the nvarchar(max) column type was used in the database table with the SQL function OPENJSON().

Entity Framework Core now uses the new native column type JSON here, provided that an SQL server version that supports it is addressed. In addition, Entity Framework Core must be informed that the target system recognizes JSON columns. This is done by calling UseSqlAzure() instead of UseSqlServer() when accessing a cloud database. For the local Microsoft SQL Server, the compatibility level must be set to 170:

builder.UseSqlServer(connstring, x => x.UseCompatibilityLevel(170));

New in Entity Framework Core 10.0 Release Candidate 1 is that Complex Types also offer JSON mapping. Microsoft introduced Complex Types in Entity Framework Core 8.0 as a better alternative to Owned Types and extended them in version 9.0, but previously no JSON mapping was offered in Complex Types, instead they were mapped to columns in the table belonging to the parent object type. Therefore, they were previously only possible for 1:1 relationships, but not for 1:N relationships. This changes in Entity Framework Core version 10.0: Here, the call ToJson() is possible for complex types in 1:1 and 1:N mapping:

modelBuilder.Entity<Company>(x =>
{
  x.ComplexProperty(p => p.Address, p=>p.ToJson()); // 1:1-Mapping. NEU: p=>p.ToJson()                                                          
  x.ComplexProperty(p => p.ManagementSet, p => p.ToJson()); // NEU: 1:N mit p=>p.ToJson()
}

According to the release notes, however, there are still problems with this in Release Candidate 1, and you should wait for Release Candidate 2 for practical use. The quick test showed that grouping with GroupBy() and the complete update of the complex type with ExecuteUpdate() in Release Candidate 1 lead to runtime errors in the JSON mapping of complex types.

Videos by heise

As a second new SQL Server data type, developers can use Microsoft.Data.SqlTypes.SqlVector<float> from the NuGet package “Microsoft.Data.SqlClient” (from version 6.1) for object-relational mapping with Entity Framework Core 10.0 from Release Candidate 1. There is also a new EF Core method EF.Functions.VectorDistance() for the SQL function VECTOR_DISTANCE(). Previously, a separate NuGet package EFCore.SqlServer.VectorSearch existed for both. However, it is not yet possible to use the SQL Server function VECTOR_SEARCH() in LINQ queries in Entity Framework Core 10.0.

The documentation contains a code example for vector data:

public class Blog
{
    // ...

    [Column(TypeName = "vector(1536)")]
    public SqlVector<float> Embedding { get; set; }
}

…

IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator = /* Set up your preferred embedding generator */;

var embedding = await embeddingGenerator.GenerateVectorAsync("Some text to be vectorized");
context.Blogs.Add(new Blog
{
    Name = "Some blog",
    Embedding = new SqlVector<float>(embedding)
});
await context.SaveChangesAsync();

…

var sqlVector = new SqlVector<float>(await embeddingGenerator.GenerateVectorAsync("Some user query to be vectorized"));
var topSimilarBlogs = context.Blogs
    .OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, sqlVector))
    .Take(3)
    .ToListAsync();

Entity Framework Core has been trying different strategies for years on one topic: the transfer of parameter sets from .NET to the database management system, for example, to search for suitable data records for a list of locations:

List<string> destinations = new List<string> { "Berlin", "New York", "Paris" };
var flights = ctx.Flights
    .Where(f => destinations.Contains(f.Destination))
    .Take(5).ToList();

Entity Framework Core-Versionen 1.0 bis 7.0 haben die Werte aus der Menge [code]destinations[/code] einzeln als statische Werte ĂĽbergeben:
SELECT TOP(@p) [f].[FlightNo], [f].[Airline], [f].[Departure], [f].[Destination], [f].[FlightDate], [f].[FreeSeats], [f].[Memo], [f].[NonSmokingFlight], [f].[Pilot_PersonID], [f].[Seats], [f].[Timestamp]
FROM [Operation].[Flight] AS [f]
WHERE [f].[NonSmokingFlight] = CAST(1 AS bit) AND [f].[FlightDate] > GETDATE() AND [f].[FreeSeats] > CAST(0 AS smallint) AND [f].[Destination] IN (N'Berlin', N'New York', N'Paris')

However, this caused many different execution plans in the database management system.

Since version 8.0, Entity Framework Core passes the list as a JSON array, which is split in the SQL command with OPENJSON():

SELECT TOP(@p) [f].[FlightNo], [f].[Airline], [f].[Departure], [f].[Destination], [f].[FlightDate], [f].[FreeSeats], [f].[Memo], [f].[NonSmokingFlight], [f].[Pilot_PersonID], [f].[Seats], [f].[Timestamp]
FROM [Operation].[Flight] AS [f]
WHERE [f].[NonSmokingFlight] = CAST(1 AS bit) AND [f].[FlightDate] > GETDATE() AND [f].[FreeSeats] > CAST(0 AS smallint) AND [f].[Destination] IN (
    SELECT [d].[value]
    FROM OPENJSON(@destinations) WITH ([value] nvarchar(30) '$') AS [d]
)

This made it difficult for the database management system to optimize the execution plans, as it no longer knew the number of parameters.

Since version 9.0, it has been possible to return to the old behavior via the EF.Constant() function or the global call TranslateParameterizedCollectionsToConstants() in the context class in OnConfiguring():

var flights1 = ctx.Flights
    .Where(f => EF.Constant(destinations).Contains(f.Destination))
    .Take(5).ToList();

With the changed standard, developers could subsequently pass the JSON array in individual cases with EF.Parameter().

Now in Entity Framework Core 10.0, Microsoft has once again implemented a new standard, namely the individual transfer of values as separate parameters:

SELECT TOP(@p) [f].[FlightNo], [f].[Airline], [f].[Departure], [f].[Destination], [f].[FlightDate], [f].[FreeSeats], [f].[Memo], [f].[NonSmokingFlight], [f].[Pilot_PersonID], [f].[Seats], [f].[Timestamp]
FROM [Operation].[Flight] AS [f]
WHERE [f].[NonSmokingFlight] = CAST(1 AS bit) AND [f].[FlightDate] > GETDATE() AND [f].[FreeSeats] > CAST(0 AS smallint) AND [f].[Destination] IN (@destinations1, @destinations2, @destinations3)

This is done in the example above with three values. However, Entity Framework Core still works in this way even with 1000 values, as a quick test showed.

The old behavior can be enforced with EF.Constant() and EF.Parameter(), as the optimal strategy also depends on how much the number of values varies at runtime. The global change to the standard is made with.

UseParameterizedCollectionMode(ParameterTranslationMode.Constant). The following values are permitted: Constant, Parameter and MultipleParameters. The TranslateParameterizedCollectionsToConstants() method first introduced in version 9.0 still exists, but it is marked as [Obsolete].

ASP.NET Core introduces new metrics for ASP.NET Core Identity in Release Candidate 1 to monitor user management, such as aspnetcore.identity.user.create.duration, aspnetcore.identity.sign_in.sign_ins and aspnetcore.identity.sign_in.two_factor_clients_forgotten.

The Persistent Component State in Blazor should now also work when using Enhanced Navigation for static server-side rendering

To validate instances of classes and records in Blazor, which Microsoft had already improved in the preview phase of .NET 10.0, there are three further innovations:

  • Validation annotations can also be defined for types and not only for properties as before.
  • The new annotation [SkipValidation] excludes types and properties from validation.
  • Likewise, all properties annotated with [JsonIgnore] are no longer validated.

There are also some minor improvements for OpenAPI schema generation, as described in the release notes.

There are also new metrics for monitoring layout performance in .NET MAUI:

  • layout.measure_count,
  • layout.measure_duration,
  • layout.arrange_count and
  • layout.arrange_duration.

The <HybridWebView> control now offers the WebViewInitializing() and WebViewInitialized() events to adjust the initialization. Comparable events previously existed in the <BlazorWebView> control (BlazorWebViewInitializing() and BlazorWebViewInitialized()). The <RefreshView> control now has the IsRefreshEnabled property in addition to IsEnabled.

The Windows Forms team writes in the release notes that the dark mode introduced in .NET 9.0 is no longer marked as experimental. At the same time, however, it also states that work on Dark Mode will continue.

The gallery shows some Windows Forms controls in dark mode.

Before the release of .NET 10.0 announced for November, a further release candidate is planned for October. Microsoft has announced November 11, 2025, as the release date for the stable version. iX, dpunkt.verlag and www.IT-Visions.de will present .NET 10.0 on November 18 at the one-day online event betterCode() .NET.

(vbr)

Don't miss any news – follow us on Facebook, LinkedIn or Mastodon.

This article was originally published in German. It was translated with technical assistance and editorially reviewed before publication.