EF Core 11 New Features: 9 Changes and the SQL They Generate

Last updated: November 11, 2026 · Tested with EF Core 11.0.0 on .NET 11.0.0 (SDK 11.0.100) and EF Core 10.0.14 on .NET 10.0.12 (SDK 10.0.401), SQL Server 2025 Express 17.0.1000.7 and LocalDB 17.0.4025.3, SQLite 3.53.4, Windows 11

Short answer: the EF Core 11 new features you’ll actually use are LINQ ones: MaxBy/MinBy and the new .NET 11 FullJoin now translate to SQL, and split queries stop joining to-one navigations they don’t need. On SQL Server you get JSON_CONTAINS for primitive collections, vector search with VECTOR_SEARCH() (it targets Azure SQL; on SQL Server 2025 it failed for me), vector columns that are no longer loaded by default, full-text indexes in the model, and temporal period columns as normal properties. Complex type properties can now be configured and indexed through c => c.Address.PostalCode. Migrations get dotnet ef database update --add and a .config/dotnet-ef.json file. I ran each one on EF Core 11.0.0 against EF Core 10 and saved the SQL. A few of them didn’t work the way the docs show.

FeatureEF Core 10.0.14EF Core 11.0.0
Property(c => c.Address.PostalCode), HasIndex on itArgumentExceptionWorks, nvarchar(10) + index
Split query with a to-one IncludeExtra INNER JOIN in every collection queryJoin removed
MaxBy / MinBy“could not be translated”TOP(1) ... ORDER BY
FullJoinNo such operator in .NET 10FULL JOIN on SQL Server and SQLite
Tags.Contains("ef-core"), level 170OPENJSON subqueryJSON_CONTAINS(...) = 1
Entity with a SqlVector<float>Vector column selectedNot selected
VectorSearch()Not availableGenerated, but failed on my SQL Server 2025
Full-text catalog/index in the modelNot availableCREATE FULLTEXT CATALOG/INDEX
Temporal PeriodStart as a CLR property“must be a shadow property”Works
dotnet ef database update --addUnrecognized option '--add'Creates and applies the migration

This post is only about what’s new. If you’re upgrading an existing app, read EF Core 11 breaking changes first. The GREATEST error on SQL Server 2019 and the missing Design package will hit you before any of this matters.

How I Tested It

One console project, built twice from the same source. A Directory.Build.props switches the target framework and the EF Core version with one property:

    <TF Condition="'$(TF)' == ''">net10.0</TF>
    <TargetFramework>$(TF)</TargetFramework>
    <EfVersion Condition="'$(TF)' == 'net10.0'">10.0.14</EfVersion>
    <EfVersion Condition="'$(TF)' == 'net11.0'">11.0.0</EfVersion>

The project references Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Sqlite at $(EfVersion). Calls that only exist in EF Core 11 sit behind #if NET11_0_OR_GREATER. SQL Server runs used a local SQL Server 2025 Express instance (17.0.1000.7, which has full-text search). For vector search I also ran against LocalDB 2025 at CU3 (17.0.4025.3). The SQL below comes from LogTo with RelationalEventId.CommandExecuted, or from ToQueryString(). I copied it from the saved output and only removed the log header lines.

1. Configure and Index Complex Type Properties Directly

Complex types are where Microsoft spent most of the EF Core 11 effort. They’re the replacement for owned entities, and EF Core 11 already warns when you map an owned collection to JSON. The change you’ll notice day to day is that a lambda can reach into the complex type:

        modelBuilder.Entity<Customer>().ComplexProperty(c => c.Address);

        modelBuilder.Entity<Customer>()
            .Property(c => c.Address.PostalCode)
            .HasMaxLength(10);

        modelBuilder.Entity<Customer>()
            .HasIndex(c => c.Address.PostalCode);

EF Core 11 builds the model, and GenerateCreateScript() shows both settings applied:

CREATE TABLE [Customers] (
    [Id] int NOT NULL IDENTITY,
    [Name] nvarchar(max) NOT NULL,
    [Address_City] nvarchar(max) NOT NULL,
    [Address_PostalCode] nvarchar(10) NOT NULL,
    [Address_Street] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_Customers] PRIMARY KEY ([Id])
);
CREATE INDEX [IX_Customers_Address_PostalCode] ON [Customers] ([Address_PostalCode]);

SQLite gets the same index (CREATE INDEX "IX_Customers_Address_PostalCode" ON "Customers" ("Address_PostalCode");). The same model on EF Core 10 fails as soon as the model is built:

ArgumentException: The expression 'c => c.Address.PostalCode' is not a valid member access expression. The expression should represent a simple property or field access: 't => t.MyProperty'. (Parameter 'memberAccessExpression')

On EF Core 10 you had to go through ComplexProperty(c => c.Address).Property(a => a.PostalCode). Keys and indexes on complex type properties are new in EF Core 11, according to the What’s new page. I only tested the index.

2. Leaner SQL for Includes of To-One Navigations

You get this one without changing any code. The query is an ordinary split query with a reference navigation and a collection:

        var split = await db.Blogs
            .Include(b => b.BlogType)
            .Include(b => b.Posts)
            .AsSplitQuery()
            .ToListAsync();

The second query, the one that loads posts, on each version:

.NET 10: SELECT [p].[Id], [p].[BlogId], [p].[PublishedOn], [p].[Title], [b].[Id], [b0].[Id]
.NET 10: FROM [Blogs] AS [b]
.NET 10: INNER JOIN [BlogTypes] AS [b0] ON [b].[BlogTypeId] = [b0].[Id]
.NET 10: INNER JOIN [Posts] AS [p] ON [b].[Id] = [p].[BlogId]
.NET 10: ORDER BY [b].[Id], [b0].[Id]

.NET 11: SELECT [p].[Id], [p].[BlogId], [p].[PublishedOn], [p].[Title], [b].[Id]
.NET 11: FROM [Blogs] AS [b]
.NET 11: INNER JOIN [Posts] AS [p] ON [b].[Id] = [p].[BlogId]
.NET 11: ORDER BY [b].[Id]

The join to BlogTypes is gone, because nothing in the posts query needs it. Without AsSplitQuery(), the single query keeps its joins but drops the redundant sort key: EF Core 10 ended with ORDER BY [b].[Id], [b0].[Id], and EF Core 11 with ORDER BY [b].[Id]. SQLite showed the same two changes. Microsoft’s benchmark on the What’s new page reports 29% (split) and 22% (single). I didn’t benchmark it, but if you have several Includes of lookup tables plus a collection, check your slowest queries after the upgrade.

3. MaxBy and MinBy Translate to SQL

Queryable.MaxBy has existed since .NET 6, so this compiles on both versions:

            var busiest = db.Blogs.MaxBy(b => b.Posts.Count());

EF Core 10 refused it:

InvalidOperationException: The LINQ expression 'DbSet<Blog>()
.MaxBy(b => b.Posts
.AsQueryable()
.Count())' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

EF Core 11 sends it to the database. The result was EF Core notes, the blog with three posts:

SELECT TOP(1) [b].[Id], [b].[BlogTypeId], [b].[Name], [b].[Tags], [b].[Details]
FROM [Blogs] AS [b]
ORDER BY (
    SELECT COUNT(*)
    FROM [Posts] AS [p]
    WHERE [b].[Id] = [p].[BlogId]) DESC

There are async versions too, MaxByAsync and MinByAsync, in EntityFrameworkQueryableExtensions:

        var first = await db.Posts.MinByAsync(p => p.PublishedOn);
SELECT TOP(1) [p].[Id], [p].[BlogId], [p].[PublishedOn], [p].[Title]
FROM [Posts] AS [p]
ORDER BY [p].[PublishedOn]

On SQLite it’s the same shape with LIMIT 1. This replaces the OrderByDescending(...).FirstOrDefault() pattern, and you no longer get an exception when you write MaxBy out of habit.

4. FullJoin: FULL OUTER JOIN from LINQ

.NET 11 adds FullJoin to LINQ, and EF Core 11 translates it. My test compares two tables of email addresses: who is an author, who is a subscriber, who is both. Either side of the result can be null, so the selector has to handle both:

        var people = await db.Authors
            .FullJoin(
                db.Subscribers,
                a => a.Email,
                s => s.Email,
                (a, s) => new
                {
                    Email = a != null ? a.Email : s!.Email,
                    IsAuthor = a != null,
                    IsSubscriber = s != null,
                })
            .OrderBy(x => x.Email)
            .ToListAsync();
SELECT CASE
    WHEN [a].[Id] IS NOT NULL THEN [a].[Email]
    ELSE [s].[Email]
END AS [Email], CASE
    WHEN [a].[Id] IS NOT NULL THEN CAST(1 AS bit)
    ELSE CAST(0 AS bit)
END AS [IsAuthor], CASE
    WHEN [s].[Id] IS NOT NULL THEN CAST(1 AS bit)
    ELSE CAST(0 AS bit)
END AS [IsSubscriber]
FROM [Authors] AS [a]
FULL JOIN [Subscribers] AS [s] ON [a].[Email] = [s].[Email]
ORDER BY CASE
    WHEN [a].[Id] IS NOT NULL THEN [a].[Email]
    ELSE [s].[Email]
END
   ana@example.com  author=True  subscriber=False
   ben@example.com  author=True  subscriber=True
   cho@example.com  author=False  subscriber=True

SQLite produced FULL JOIN "Subscribers" AS "s" ON "a"."Email" = "s"."Email" and returned the same three rows. EF checks [a].[Id] IS NOT NULL rather than the email column, which is correct: the key tells it whether that side matched. Before this, you had to write two left joins and a Union, or raw SQL. On net10.0 there’s no FullJoin method at all, so this code only compiles on .NET 11.

5. JSON on SQL Server: JSON_CONTAINS and JsonPathExists

A List<string> property is stored as a JSON array. A Contains query over it has always gone through OPENJSON. Set the compatibility level to 170 (SQL Server 2025) and EF Core 11 uses the new JSON_CONTAINS function:

            var query = db.Blogs.Where(b => b.Tags.Contains("ef-core")).Select(b => b.Name);
.NET 11: == Tags.Contains("ef-core"), compatibility level default
.NET 11: SELECT [b].[Name]
.NET 11: FROM [Blogs] AS [b]
.NET 11: WHERE N'ef-core' IN (
.NET 11: SELECT [t].[value]
.NET 11: FROM OPENJSON([b].[Tags]) WITH ([value] nvarchar(max) '$') AS [t]
.NET 11: )

.NET 11: == Tags.Contains("ef-core"), compatibility level 170
.NET 11: SELECT [b].[Name]
.NET 11: FROM [Blogs] AS [b]
.NET 11: WHERE JSON_CONTAINS([b].[Tags], N'ef-core') = 1

Both return EF Core notes. EF Core 10 at level 170 still generated the OPENJSON version. The default level in EF Core 11 is 160, so you only get this after you opt in with o.UseCompatibilityLevel(170), and only when your server really is SQL Server 2025 or Azure SQL.

There are two new EF.Functions for JSON columns. My Blog.Details is a complex type mapped with ToJson():

                .Where(b => EF.Functions.JsonPathExists(b.Details, "$.Description"))
                    .Where(b => EF.Functions.JsonContains(b.Details, 8, "$.Rating", null) == 1)
WHERE JSON_PATH_EXISTS([b].[Details], N'$.Description') = 1
WHERE JSON_CONTAINS([b].[Details], 8, N'$.Rating') = 1

JsonPathExists also works on SQLite, where it becomes WHERE json_type("b"."Details", '$.Description') IS NOT NULL. One thing caught me out: it returned both blogs, even though one has no description. EF writes null properties into the JSON document, so the path does exist:

EF Core notes|{"Description":"Notes","Rating":8}
ASP.NET diary|{"Description":null,"Rating":5}

To find rows where a value is missing, filter on the property itself (b.Details.Description == null). JsonPathExists only helps with JSON you didn’t write through EF. JsonContains is also marked experimental, so it doesn’t compile until you suppress the diagnostic:

Tests.cs(113,33): error EF9106: 'Microsoft.EntityFrameworkCore.SqlServerDbFunctionsExtensions.JsonContains(Microsoft.EntityFrameworkCore.DbFunctions, object, object, string?, int?)' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

6. Vector Search on SQL Server: What Worked and What Didn’t

This is the feature I expected most from, and it gave me the most trouble. The model is a Doc with a SqlVector<float> Embedding column of type vector(3) and 200 rows.

Vectors are no longer loaded with the entity. The same db.Docs.OrderBy(d => d.Id).Take(2) on each version:

.NET 10: SELECT TOP(@p) [d].[Id], [d].[Embedding], [d].[Title]
.NET 11: SELECT TOP(@p) [d].[Id], [d].[Title]

That’s a real saving when embeddings have 1,536 dimensions. But look at what the entity holds afterwards:

   Doc 1: Embedding.IsNull=False, Length=0

IsNull is false, so code that checks for “no embedding yet” before re-computing one will be wrong. If you need the vector, project it explicitly (Select(d => new { d.Title, d.Embedding })). That worked on 11.0.0 and returned [1.000, 0.008, 0.100]. Exact search with EF.Functions.VectorDistance worked on both versions and returned Doc 6, Doc 7, Doc 5.

The vector index needs HasMetric. The What’s new page shows HasVectorIndex(b => b.Embedding, "cosine"). On 11.0.0 the second parameter is the index name, so that line creates an index called cosine with no metric:

   InvalidOperationException: Vector index ''cosine'' on entity type 'Doc' must specify a similarity metric. Call 'HasMetric' on the vector index builder.

This version works and generates the expected DDL:

            modelBuilder.Entity<Doc>()
                .HasVectorIndex(d => d.Embedding, "IX_Docs_Embedding")
                .HasMetric("cosine");
CREATE VECTOR INDEX [IX_Docs_Embedding] ON [Docs]([Embedding]) WITH (METRIC = 'cosine');

On SQL Server 2025 that statement only runs after ALTER DATABASE SCOPED CONFIGURATION SET PREVIEW_FEATURES = ON;. Without it I got Unknown object type 'VECTOR' used in a CREATE, DROP, or ALTER statement. Once the index existed, inserts failed. That’s a SQL Server 2025 restriction, not EF, but EF’s error is what you’ll see:

   DbUpdateException: Data modification statement failed because table 'Docs' has a vector index on it.

VectorSearch() generated SQL my SQL Server 2025 rejects. The LINQ and the SQL from 11.0.0:

        var ann = indexed.Docs
            .VectorSearch(d => d.Embedding, query, "cosine")
            .OrderBy(r => r.Distance)
            .Take(3)
            .WithApproximate()
            .Select(r => new { r.Value.Title, r.Distance });
SELECT TOP(@p1) WITH APPROXIMATE [d].[Title], [v].[Distance]
FROM VECTOR_SEARCH(
    TABLE = [Docs] AS [d],
    COLUMN = [Embedding],
    SIMILAR_TO = @p,
    METRIC = 'cosine'
) AS [v]
ORDER BY [v].[Distance]
   SqlException: Incorrect syntax near 'APPROXIMATE'.

Without WithApproximate() it failed with SqlException: Incorrect syntax near 'TOP_N'. I got the same two errors on SQL Server 2025 RTM (17.0.1000.7) and on LocalDB at CU3 (17.0.4025.3). Both servers expect the older syntax, where TOP_N is an argument of VECTOR_SEARCH. Written by hand that way, the query ran against the same table and index and returned Doc 6, Doc 7 and Doc 5. The EF pull request that added WithApproximate (dotnet/efcore#38144) says it targets “the latest Azure SQL VECTOR_SEARCH() syntax”. So in 11.0.0, VectorSearch() is for Azure SQL, or for a SQL Server build that has caught up. I couldn’t test Azure SQL. On a boxed SQL Server 2025 up to CU3, keep using VectorDistance. VectorSearch, WithApproximate and HasVectorIndex are all experimental (EF9105), like JsonContains.

One more small thing: ToQueryString() can’t print a vector parameter. It writes DECLARE @p sql_variant = Microsoft.Data.SqlTypes.SqlVector`1[System.Single];, so don’t paste that script into SSMS expecting it to run.

7. Full-Text Search Indexes in the Model

Full-text search used to mean raw SQL in a migration, because CREATE FULLTEXT CATALOG wasn’t something EF knew about. EF Core 11 can configure it:

        modelBuilder.HasFullTextCatalog("ftCatalog");

        modelBuilder.Entity<Article>()
            .HasFullTextIndex(a => a.Body)
            .UseKeyIndex("PK_Articles")
            .UseCatalog("ftCatalog");
CREATE FULLTEXT CATALOG [ftCatalog];
CREATE FULLTEXT INDEX ON [Articles]([Body]) KEY INDEX [PK_Articles] ON [ftCatalog];
   EnsureCreated: OK

The new FreeTextTable and ContainsTable return a rank you can sort by. On 11.0.0 they return the key and the rank, not the entity, so you join back:

        var ranked = db.Articles
            .FreeTextTable<Article, int>("tracking entities", a => a.Body)
            .Join(db.Articles, ft => ft.Key, a => a.Id, (ft, a) => new { a.Title, ft.Rank })
            .OrderByDescending(x => x.Rank);
SELECT [a0].[Title], [f].[RANK] AS [Rank]
FROM FREETEXTTABLE([Articles], [Body], @p) AS [f]
INNER JOIN [Articles] AS [a0] ON [f].[KEY] = [a0].[Id]
ORDER BY [f].[RANK] DESC
   Tracking  rank 36

The What’s new page’s sample (.FreeTextTable("John", b => b.FullName).Select(r => new { Blog = r.Value, Rank = r.Rank })) doesn’t compile on 11.0.0. I pasted it in as written:

LearnSample.cs(9,14): error CS0411: The type arguments for method 'SqlServerQueryableExtensions.FreeTextTable<T, TKey>(DbSet<T>, string, Expression<Func<T, object>>?, string?, int?)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
LearnSample.cs(10,41): error CS1061: 'FullTextSearchResult<TKey>' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'FullTextSearchResult<TKey>' could be found (are you missing a using directive or an assembly reference?)

Give the key type explicitly and use Key, as above. Full-text has to be installed on the server. My SQL Server 2025 Express instance had it (IsFullTextInstalled = 1) and LocalDB didn’t (0). The index fills in the background, so a test that inserts rows and searches straight away can get zero rows. Mine waits for FULLTEXTCATALOGPROPERTY('ftCatalog', 'ItemCount') first.

8. Temporal Tables: Period Columns as Real Properties

Until now, PeriodStart and PeriodEnd had to be shadow properties, so every history query was full of EF.Property<DateTime>(e, "PeriodStart"). EF Core 11 maps them to ordinary properties:

        modelBuilder.Entity<Employee>()
            .ToTable("Employees", t => t.IsTemporal(p =>
            {
                p.HasPeriodStart(e => e.PeriodStart);
                p.HasPeriodEnd(e => e.PeriodEnd);
            }));
            var history = db.Employees
                .TemporalAll()
                .OrderBy(e => e.PeriodStart)
                .Select(e => new { e.Name, e.Position, e.PeriodStart, e.PeriodEnd });
SELECT [e].[Name], [e].[Position], [e].[PeriodStart], [e].[PeriodEnd]
FROM [Employees] FOR SYSTEM_TIME ALL AS [e]
ORDER BY [e].[PeriodStart]
   Developer         02:54:13.649 -> 02:54:13.729
   Senior developer  02:54:13.729 -> current
   tracked entity PeriodStart: 2026-11-11

After SaveChanges the tracked entity had its PeriodStart filled in by SQL Server. The values are UTC, so the date can differ from your local date. On EF Core 10, a CLR property with that name (configured with the string overload, which is all EF Core 10 has) stops the model from building:

   InvalidOperationException: Period property 'Employee.PeriodStart' must be a shadow property.

9. Migrations and dotnet ef

Create and apply in one command. database update takes --add. It scaffolds the migration, compiles it with Roslyn and applies it:

## dotnet ef database update InitialCreate --add --project Tooling
Build started...
Build succeeded.
Creating and applying migration 'InitialCreate'.
Applying migration '20261111031951_InitialCreate'.
Migration '20261111031951_InitialCreate' was successfully created and applied.

The three migration files were written to Migrations/ as usual, and the app then reported Applied migrations: 20261111031951_InitialCreate. The dotnet-ef 10.0.14 tool answers the same command with Unrecognized option '--add'. You still need the Design package in the startup project, as covered in the breaking-changes post. If database update refuses to run because of pending model changes, see fixing PendingModelChangesWarning.

Merge conflicts on purpose. The snapshot now records the latest migration, so two branches that each add a migration conflict on this line instead of merging silently:

    // If you encounter a merge conflict in the line below, it means you need to
    // discard one of the migration branches and recreate its migrations on top of
    // the other branch. See https://aka.ms/efcore-docs-migrations-conflicts for more info.
    public override string LastMigrationId => "20261111031951_InitialCreate";

A config file for the options you type every time. With this in .config/dotnet-ef.json, dotnet ef migrations list works from the solution folder without --project:

{
  "project": "Tooling",
  "startupProject": "Tooling",
  "context": "ShopContext"
}

dotnet-ef 10 ignores the file: No project was found. Change the current working directory or use the --project option. The other tooling change is useful in CI. Build started... and the other status lines now go to stderr, so dotnet ef migrations script > migrate.sql gives you only SQL. With dotnet-ef 10 those lines went to stdout.

Relationships without a database constraint. For legacy schemas or sync jobs that insert children before parents:

        modelBuilder.Entity<LegacyCustomer>()
            .HasMany(c => c.Orders)
            .WithOne(o => o.Customer)
            .HasForeignKey(o => o.CustomerId)
            .ExcludeForeignKeyFromMigrations();
CREATE TABLE [Orders] (
    [Id] int NOT NULL IDENTITY,
    [CustomerId] int NOT NULL,
    CONSTRAINT [PK_Orders] PRIMARY KEY ([Id])
);
CREATE INDEX [IX_Orders_CustomerId] ON [Orders] ([CustomerId]);

There’s no FOREIGN KEY constraint, but the index is still there, and EF still treats the relationship as normal for queries and change tracking. That includes identity resolution, so “instance cannot be tracked” errors work exactly as before.

Two Smaller Ones

EF.Functions.DateTrunc on SQL Server, handy for reports grouped by month:

            .GroupBy(p => EF.Functions.DateTrunc("month", p.PublishedOn))
    SELECT DATETRUNC(month, [p].[PublishedOn]) AS [Key]
   2026-09-01: 1
   2026-10-01: 3

Ordered string.Join on SQLite. The What’s new page shows this through a collection navigation (b.Posts.OrderByDescending(...)). On 11.0.0 that version still loaded every post and joined the strings on the client, exactly like EF Core 10. It was translated only when I grouped first:

                .GroupBy(p => p.BlogId)
                    Posts = string.Join(", ", g.OrderByDescending(p => p.Id).Select(p => p.Title)),
SELECT "p"."BlogId", COALESCE(group_concat("p"."Title", ', ' ORDER BY "p"."Id" DESC), '') AS "Posts"
FROM "Posts" AS "p"
GROUP BY "p"."BlogId"
   sqlite_version(): 3.53.4

EF Core 10 ran the same GroupBy as a subquery plus a LEFT JOIN to Posts, then joined on the client. SQL Server already translated this to STRING_AGG ... WITHIN GROUP on both versions.

Gotchas I Hit on EF Core 11

  • VectorSearch() SQL fails on SQL Server 2025 RTM and CU3 with Incorrect syntax near 'TOP_N' / 'APPROXIMATE'. Use VectorDistance there.
  • HasVectorIndex(x, "cosine") names the index “cosine”. Add .HasMetric("cosine").
  • Unloaded vectors aren’t null. IsNull=False, Length=0 after a normal entity query.
  • Experimental APIs fail the build: EF9105 for the vector APIs, EF9106 for JsonContains. Suppress them per file, so you notice when they become stable.
  • JsonPathExists is true for null properties that EF wrote into the JSON.
  • The FreeTextTable sample on Learn doesn’t compile (CS0411, CS1061 on Value).
  • The SQLite ordered string.Join example wasn’t translated through a navigation, only after GroupBy.
  • JSON_CONTAINS needs UseCompatibilityLevel(170). The default (160) keeps OPENJSON.

What I Didn’t Test

  • Cosmos DB (complex types, bulk execution, transactional batches, session tokens). I have no Cosmos account.
  • Azure SQL, so I couldn’t confirm that VectorSearch() works where it was designed to.
  • Complex types with TPT/TPC, keys on complex type properties, JSON indexes, the DateTimeOffset translations, GroupBy materialization fixes, and the UInt128 parameter support in Microsoft.Data.Sqlite.
  • NativeAOT and precompiled queries. People search for “EF Core 11 AOT”, but the What’s new page has no section on it, and I didn’t test it.
  • Performance. I captured SQL, not timings.

FAQ

What are the main new features in EF Core 11?

For relational databases: MaxBy/MinBy and FullJoin translation, fewer joins and sort keys for to-one Includes, complex type properties you can configure and index by path, and JSON_CONTAINS, vector search, full-text index and temporal property support on SQL Server. Migrations get database update --add, a LastMigrationId in the snapshot, .config/dotnet-ef.json and ExcludeForeignKeyFromMigrations().

Does EF Core 11 run on .NET 10?

No. The 11.0.0 packages support only net11.0, and restore on net10.0 fails with NU1202: Package Microsoft.EntityFrameworkCore.SqlServer 11.0.0 is not compatible with net10.0. The .NET 11 upgrade guide covers moving the app first.

Do I need SQL Server 2025 for the new features?

Only for some of them. MaxBy, FullJoin, the join pruning, complex type indexes, temporal properties and the migrations features worked the same on SQLite or with the default compatibility level. JSON_CONTAINS needs level 170, and vector indexes need SQL Server 2025 with preview features turned on.

Is vector search in EF Core 11 production-ready?

Not in 11.0.0. The APIs are marked experimental (EF9105), and SQL Server marks vector indexes as a preview feature. The generated VECTOR_SEARCH syntax also failed on my SQL Server 2025 instances. EF.Functions.VectorDistance, which arrived in EF Core 10, is the part that worked.

Related: What’s new in EF Core 11 (Learn) · VECTOR_SEARCH (Transact-SQL)

Similar Posts

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *