From 9d2ace4c9f57927020ad2c39055a380623398830 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 08:38:42 +0000 Subject: [PATCH 1/4] Initial plan From c415658d05d0964a05db65fa256dcc67044f53ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 08:44:01 +0000 Subject: [PATCH 2/4] Document vector properties not loaded by default Document https://github.com/dotnet/efcore/issues/37279 Co-authored-by: roji <1862641+roji@users.noreply.github.com> --- .../providers/sql-server/vector-search.md | 63 ++++++++++++++++++- .../core/what-is-new/ef-core-11.0/whatsnew.md | 23 +++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/entity-framework/core/providers/sql-server/vector-search.md b/entity-framework/core/providers/sql-server/vector-search.md index 5c648aa749..686ca099c5 100644 --- a/entity-framework/core/providers/sql-server/vector-search.md +++ b/entity-framework/core/providers/sql-server/vector-search.md @@ -66,6 +66,65 @@ await context.SaveChangesAsync(); Once you have embeddings saved to your database, you're ready to perform vector similarity search over them. +## Vector properties not loaded by default + +> [!NOTE] +> This feature is being introduced in EF Core 11, which is currently in preview. + +In the vast majority of cases, vector properties (embeddings) are ingested into the database and then used for vector search, without ever needing to be read back. Since vector columns can be quite large—containing hundreds or thousands of floating-point values—EF Core 11 no longer loads them by default. + +When querying entities that contain vector properties, EF excludes the vector column from the SQL `SELECT` statement: + +```csharp +var blogs = await context.Blogs.OrderBy(b => b.Name).ToListAsync(); +``` + +This generates the following SQL, which does **not** include the `Embedding` column: + +```sql +SELECT [b].[Id], [b].[Name] +FROM [Blogs] AS [b] +ORDER BY [b].[Name] +``` + +The `Embedding` property on the returned entities will be `null` (or the sentinel value for the type), and if change tracking is enabled, the change tracker will record the property as not loaded (`entry.Property(e => e.Embedding).IsLoaded == false`). + +Vector properties can still be used in filters and orderings—EF will correctly reference the column in `WHERE` and `ORDER BY` clauses while still omitting it from the projected entity. For example, `VectorDistance()` still generates the correct SQL even though the embedding is not returned: + +```csharp +var topSimilarBlogs = await context.Blogs + .OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, sqlVector)) + .Take(3) + .ToListAsync(); +``` + +```sql +SELECT TOP(3) [b].[Id], [b].[Name] +FROM [Blogs] AS [b] +ORDER BY VECTOR_DISTANCE('cosine', [b].[Embedding], @sqlVector) +``` + +If you need to explicitly load a vector property, use a projection: + +```csharp +var embeddings = await context.Blogs + .Select(b => new { b.Id, b.Embedding }) + .ToListAsync(); +``` + +The underlying mechanism is the `IsAutoLoaded` metadata flag. While EF automatically sets this to `false` for `SqlVector` properties by convention, you can configure it for any non-key property as well: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + modelBuilder.Entity() + .Property(b => b.LargeData) + .Metadata.IsAutoLoaded = false; +} +``` + +Properties with `IsAutoLoaded = false` are excluded from entity projections in queries but can still be used in filters, orderings, and explicit projections. Note that key properties, discriminator properties, concurrency tokens, and constructor-bound properties cannot be configured as not auto-loaded. + ## Exact search with VECTOR_DISTANCE() The [`EF.Functions.VectorDistance()`](/sql/t-sql/functions/vector-distance-transact-sql) function computes the *exact* distance between two vectors. Use it to perform similarity search for a given user query: @@ -138,7 +197,7 @@ foreach (var (article, score) in blogs) This translates to the following SQL: ```sql -SELECT [v].[Id], [v].[Embedding], [v].[Name] +SELECT [v].[Id], [v].[Name] FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN) ``` @@ -205,7 +264,7 @@ This query: The query produces the following SQL: ```sql -SELECT TOP(@p3) [a0].[Id], [a0].[Content], [a0].[Embedding], [a0].[Title] +SELECT TOP(@p3) [a0].[Id], [a0].[Content], [a0].[Title] FROM FREETEXTTABLE([Articles], *, @p, @p1) AS [f] LEFT JOIN VECTOR_SEARCH( TABLE = [Articles] AS [a0], diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index a519703cec..aed3377253 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -312,6 +312,29 @@ This translates to the SQL Server [`VECTOR_SEARCH()`](/sql/t-sql/functions/vecto For more information, see the [full documentation on vector search](xref:core/providers/sql-server/vector-search). + + +### Vector properties not loaded by default + +EF Core 11 changes how vector properties are loaded: `SqlVector` columns are no longer included in `SELECT` statements when materializing entities. Since vectors can be quite large—containing hundreds or thousands of floating-point numbers—this avoids unnecessary data transfer in the common case where vectors are ingested and used for search but not read back. + +```csharp +// Vector column is excluded from the projected entity +var blogs = await context.Blogs.OrderBy(b => b.Name).ToListAsync(); +// Generates: SELECT [b].[Id], [b].[Name] FROM [Blogs] AS [b] + +// Explicit projection still loads the vector +var embeddings = await context.Blogs + .Select(b => new { b.Id, b.Embedding }) + .ToListAsync(); +``` + +Vector properties can still be used in `WHERE` and `ORDER BY` clauses—including with `VectorDistance()` and `VectorSearch()`—and EF will correctly include them in the SQL, just not in the entity projection. The change tracker marks non-loaded properties with `IsLoaded = false`. + +The underlying mechanism is the `IsAutoLoaded` metadata flag. EF sets this to `false` for vector properties by convention, but it can also be configured for any other non-key property. + +For more information, see [Vector properties not loaded by default](xref:core/providers/sql-server/vector-search#vector-properties-not-loaded-by-default). + ### Full-text search table-valued functions From f97a24b88fd37367d63e811c15ce2c326b49b4c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 08:52:07 +0000 Subject: [PATCH 3/4] Simplify vector not-auto-loaded docs per review feedback Co-authored-by: roji <1862641+roji@users.noreply.github.com> --- .../providers/sql-server/vector-search.md | 58 +------------------ .../core/what-is-new/ef-core-11.0/whatsnew.md | 6 +- 2 files changed, 2 insertions(+), 62 deletions(-) diff --git a/entity-framework/core/providers/sql-server/vector-search.md b/entity-framework/core/providers/sql-server/vector-search.md index 686ca099c5..19b2871d1b 100644 --- a/entity-framework/core/providers/sql-server/vector-search.md +++ b/entity-framework/core/providers/sql-server/vector-search.md @@ -66,64 +66,8 @@ await context.SaveChangesAsync(); Once you have embeddings saved to your database, you're ready to perform vector similarity search over them. -## Vector properties not loaded by default - > [!NOTE] -> This feature is being introduced in EF Core 11, which is currently in preview. - -In the vast majority of cases, vector properties (embeddings) are ingested into the database and then used for vector search, without ever needing to be read back. Since vector columns can be quite large—containing hundreds or thousands of floating-point values—EF Core 11 no longer loads them by default. - -When querying entities that contain vector properties, EF excludes the vector column from the SQL `SELECT` statement: - -```csharp -var blogs = await context.Blogs.OrderBy(b => b.Name).ToListAsync(); -``` - -This generates the following SQL, which does **not** include the `Embedding` column: - -```sql -SELECT [b].[Id], [b].[Name] -FROM [Blogs] AS [b] -ORDER BY [b].[Name] -``` - -The `Embedding` property on the returned entities will be `null` (or the sentinel value for the type), and if change tracking is enabled, the change tracker will record the property as not loaded (`entry.Property(e => e.Embedding).IsLoaded == false`). - -Vector properties can still be used in filters and orderings—EF will correctly reference the column in `WHERE` and `ORDER BY` clauses while still omitting it from the projected entity. For example, `VectorDistance()` still generates the correct SQL even though the embedding is not returned: - -```csharp -var topSimilarBlogs = await context.Blogs - .OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, sqlVector)) - .Take(3) - .ToListAsync(); -``` - -```sql -SELECT TOP(3) [b].[Id], [b].[Name] -FROM [Blogs] AS [b] -ORDER BY VECTOR_DISTANCE('cosine', [b].[Embedding], @sqlVector) -``` - -If you need to explicitly load a vector property, use a projection: - -```csharp -var embeddings = await context.Blogs - .Select(b => new { b.Id, b.Embedding }) - .ToListAsync(); -``` - -The underlying mechanism is the `IsAutoLoaded` metadata flag. While EF automatically sets this to `false` for `SqlVector` properties by convention, you can configure it for any non-key property as well: - -```csharp -protected override void OnModelCreating(ModelBuilder modelBuilder) -{ - modelBuilder.Entity() - .Property(b => b.LargeData) - .Metadata.IsAutoLoaded = false; -} -``` - -Properties with `IsAutoLoaded = false` are excluded from entity projections in queries but can still be used in filters, orderings, and explicit projections. Note that key properties, discriminator properties, concurrency tokens, and constructor-bound properties cannot be configured as not auto-loaded. +> Starting with EF Core 11, vector properties are not loaded by default when querying entities, since vectors are typically large and are rarely needed to be read back. Prior to EF Core 11, vector properties were always loaded like any other property. ## Exact search with VECTOR_DISTANCE() diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index aed3377253..255fee72ec 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -329,11 +329,7 @@ var embeddings = await context.Blogs .ToListAsync(); ``` -Vector properties can still be used in `WHERE` and `ORDER BY` clauses—including with `VectorDistance()` and `VectorSearch()`—and EF will correctly include them in the SQL, just not in the entity projection. The change tracker marks non-loaded properties with `IsLoaded = false`. - -The underlying mechanism is the `IsAutoLoaded` metadata flag. EF sets this to `false` for vector properties by convention, but it can also be configured for any other non-key property. - -For more information, see [Vector properties not loaded by default](xref:core/providers/sql-server/vector-search#vector-properties-not-loaded-by-default). +Vector properties can still be used in `WHERE` and `ORDER BY` clauses—including with `VectorDistance()` and `VectorSearch()`—and EF will correctly include them in the SQL, just not in the entity projection. From dc55ed938c2c10334e2b0fecda14e90ba9bc4698 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 09:21:51 +0000 Subject: [PATCH 4/4] Add low-impact breaking change entry for SqlVector not loaded by default Co-authored-by: roji <1862641+roji@users.noreply.github.com> --- .../ef-core-11.0/breaking-changes.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 047b586890..b17a46ad7a 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -22,6 +22,7 @@ This page documents API and behavior changes that have the potential to break ex | [EF Core now throws by default when no migrations are found](#migrations-not-found) | Low | | [`EFOptimizeContext` MSBuild property has been removed](#ef-optimize-context-removed) | Low | | [EF tools packages no longer reference Microsoft.EntityFrameworkCore.Design](#ef-tools-no-design-dep) | Low | +| [SqlVector properties are no longer loaded by default](#sqlvector-not-auto-loaded) | Low | ## Medium-impact changes @@ -141,3 +142,36 @@ If your project relies on `Microsoft.EntityFrameworkCore.Design` being brought i ```xml ``` + + + +### SqlVector properties are no longer loaded by default + +[Tracking Issue #37279](https://github.com/dotnet/efcore/issues/37279) + +#### Old behavior + +Previously, when querying entities with `SqlVector` properties, EF Core included the vector column in `SELECT` statements and populated the property on the returned entity. + +#### New behavior + +Starting with EF Core 11.0, `SqlVector` properties are no longer included in `SELECT` statements when materializing entities. The property will be `null` on returned entities. + +Vector properties can still be used in `WHERE` and `ORDER BY` clauses—including with `VectorDistance()` and `VectorSearch()`—they just won't be included in the entity projection. + +#### Why + +Vector columns can be very large, containing hundreds or thousands of floating-point values. In the vast majority of cases, vectors are written to the database and then used for search, without needing to be read back. Excluding them from `SELECT` by default avoids unnecessary data transfer. + +#### Mitigations + +> [!NOTE] +> A mechanism for opting vector properties back into automatic loading will be introduced later in the EF Core 11 release. + +If you need to read back vector values, use an explicit projection: + +```csharp +var embeddings = await context.Blogs + .Select(b => new { b.Id, b.Embedding }) + .ToListAsync(); +```