diff --git a/entity-framework/core/providers/sql-server/vector-search.md b/entity-framework/core/providers/sql-server/vector-search.md index 5c648aa749..11ab9096fb 100644 --- a/entity-framework/core/providers/sql-server/vector-search.md +++ b/entity-framework/core/providers/sql-server/vector-search.md @@ -66,6 +66,9 @@ await context.SaveChangesAsync(); Once you have embeddings saved to your database, you're ready to perform vector similarity search over them. +> [!NOTE] +> 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() 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: @@ -126,7 +129,7 @@ Once you have a vector index, use the `VectorSearch()` extension method on your ```csharp var blogs = await context.Blogs - .VectorSearch(b => b.Embedding, "cosine", embedding, topN: 5) + .VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5) .ToListAsync(); foreach (var (article, score) in blogs) @@ -138,7 +141,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], [v].[Distance] FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN) ``` @@ -148,7 +151,7 @@ The `topN` parameter specifies the maximum number of results to return. ```csharp var searchResults = await context.Blogs - .VectorSearch(b => b.Embedding, "cosine", embedding, topN: 5) + .VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5) .Where(r => r.Distance < 0.05) .Select(r => new { Blog = r.Value, Distance = r.Distance }) .ToListAsync(); @@ -205,7 +208,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/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 047b586890..7d822d61ea 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(); +``` 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..301b82ee44 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 @@ -302,7 +302,7 @@ Once you have a vector index, you can use the `VectorSearch()` extension method ```csharp var blogs = await context.Blogs - .VectorSearch(b => b.Embedding, "cosine", embedding, topN: 5) + .VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5) .ToListAsync(); ``` @@ -312,6 +312,25 @@ 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. + ### Full-text search table-valued functions