Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions entity-framework/core/providers/sql-server/vector-search.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
roji marked this conversation as resolved.
Outdated

> [!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<T>` properties by convention, you can configure it for any non-key property as well:

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.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:
Expand Down Expand Up @@ -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]
Comment thread
roji marked this conversation as resolved.
Outdated
FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN)
```

Expand Down Expand Up @@ -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],
Expand Down
23 changes: 23 additions & 0 deletions entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

<a name="sqlserver-vector-not-auto-loaded"></a>

### Vector properties not loaded by default

EF Core 11 changes how vector properties are loaded: `SqlVector<T>` 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]
Comment thread
roji marked this conversation as resolved.
Outdated

// 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.
Comment thread
roji marked this conversation as resolved.
Outdated

For more information, see [Vector properties not loaded by default](xref:core/providers/sql-server/vector-search#vector-properties-not-loaded-by-default).
Comment thread
roji marked this conversation as resolved.
Outdated

<a name="sqlserver-full-text-tvf"></a>

### Full-text search table-valued functions
Expand Down