diff --git a/entity-framework/core/dbcontext-configuration/index.md b/entity-framework/core/dbcontext-configuration/index.md index 00a24264a4..b4dfce2533 100644 --- a/entity-framework/core/dbcontext-configuration/index.md +++ b/entity-framework/core/dbcontext-configuration/index.md @@ -90,8 +90,6 @@ The final result is an `ApplicationDbContext` instance created for each request Read further in this article to learn more about configuration options. See [Dependency injection in ASP.NET Core](/aspnet/core/fundamentals/dependency-injection) for more information. - - ## Basic DbContext initialization with 'new' `DbContext` instances can be constructed with `new` in C#. Configuration can be performed by overriding the `OnConfiguring` method, or by passing options to the constructor. For example: @@ -425,6 +423,80 @@ Any code that explicitly executes multiple threads in parallel should ensure tha Using dependency injection, this can be achieved by either registering the context as scoped, and creating scopes (using `IServiceScopeFactory`) for each thread, or by registering the `DbContext` as transient (using the overload of `AddDbContext` which takes a `ServiceLifetime` parameter). + + +## ConfigureDbContext for configuration composition + +> [!NOTE] +> This section covers intermediate-level usage of EF Core primarily intended for reusable libraries and components. Most applications should use the `AddDbContextFactory` pattern described earlier in this article. + +Starting with EF Core 9.0, you can use to apply additional configuration to a `DbContext` either before or after the `AddDbContext` call. This is particularly useful for composing non-conflicting configuration in reusable components or tests. + +### Basic ConfigureDbContext usage + +`ConfigureDbContext` allows you to add configuration in a reusable library or component without replacing the entire provider configuration: + + +[!code-csharp[BasicConfigureDbContext](../../../samples/core/Miscellaneous/ConfiguringDbContext/ConfigureDbContextSample.cs?name=BasicConfigureDbContext)] + +### Provider-specific configuration without connection strings + +To apply provider-specific configuration you can use provider-specific configuration methods without supplying the connection string. The SQL Server provider also includes `ConfigureSqlEngine` for this case. See [SQL Server-specific batching behavior](xref:core/providers/sql-server/misc#configuresqlengine) for more information. + + +[!code-csharp[ProviderSpecificConfiguration](../../../samples/core/Miscellaneous/ConfiguringDbContext/ConfigureDbContextSample.cs?name=ProviderSpecificConfiguration)] + +### ConfigureDbContext and AddDbContext precedence + +When both `ConfigureDbContext` and `AddDbContext` are used, or when multiple calls to these methods are made, the configuration is applied in the order the methods are called, with later calls taking precedence for conflicting options. + +For non-conflicting options (like adding logging, interceptors, or other settings), all configurations are composed together: + + +[!code-csharp[ConfigurationComposition](../../../samples/core/Miscellaneous/ConfiguringDbContext/ConfigureDbContextSample.cs?name=ConfigurationComposition)] + +For conflicting options, the last configuration wins. See [breaking changes in EF Core 8.0](xref:core/what-is-new/ef-core-8.0/breaking-changes#AddDbContext) for more information about this behavior change. + +> [!NOTE] +> Configuring a different provider will not remove the previous provider configuration. This can lead to errors when creating the context. To completely replace the provider, you need to remove the context registration and re-add it, or create a new service collection. + + + ## More reading - Read [Dependency Injection](/aspnet/core/fundamentals/dependency-injection) to learn more about using DI. diff --git a/entity-framework/core/modeling/data-seeding.md b/entity-framework/core/modeling/data-seeding.md index 22759ad633..304d430c88 100644 --- a/entity-framework/core/modeling/data-seeding.md +++ b/entity-framework/core/modeling/data-seeding.md @@ -21,25 +21,25 @@ There are several ways this can be accomplished in EF Core: ## Configuration options `UseSeeding` and `UseAsyncSeeding` methods -EF 9 introduced `UseSeeding` and `UseAsyncSeeding` methods, which provide a convenient way of seeding the database with initial data. These methods aim to improve the experience of using custom initialization logic (explained below). They provide one clear location where all the data seeding code can be placed. Moreover, the code inside `UseSeeding` and `UseAsyncSeeding` methods is protected by the [migration locking mechanism](/ef/core/what-is-new/ef-core-9.0/whatsnew#concurrent-migrations) to prevent concurrency issues. +EF 9 introduced and methods, which provide a convenient way of seeding the database with initial data. These methods aim to improve the experience of using custom initialization logic (explained below). They provide one clear location where all the data seeding code can be placed. Moreover, the code inside and methods is protected by the [migration locking mechanism](/ef/core/what-is-new/ef-core-9.0/whatsnew#concurrent-migrations) to prevent concurrency issues. -The new seeding methods are called as part of [`EnsureCreated`](xref:Microsoft.EntityFrameworkCore.Storage.IDatabaseCreator.EnsureCreated) operation, [`Migrate`](/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions.migrate) and `dotnet ef database update` command, even if there are no model changes and no migrations were applied. +The new seeding methods are called as part of operation, and `dotnet ef database update` command, even if there are no model changes and no migrations were applied. > [!TIP] -> Using `UseSeeding` and `UseAsyncSeeding` is the recommended way of seeding the database with initial data when working with EF Core. +> Using and is the recommended way of seeding the database with initial data when working with EF Core. These methods can be set up in the [options configuration step](/ef/core/dbcontext-configuration/#dbcontextoptions). Here is an example: [!code-csharp[ContextOptionSeeding](../../../samples/core/Modeling/DataSeeding/DataSeedingContext.cs?name=ContextOptionSeeding)] > [!NOTE] -> `UseSeeding` is called from the `EnsureCreated` method, and `UseAsyncSeeding` is called from the `EnsureCreatedAsync` method. When using this feature, it is recommended to implement both `UseSeeding` and `UseAsyncSeeding` methods using similar logic, even if the code using EF is asynchronous. EF Core tooling currently relies on the synchronous version of the method and will not seed the database correctly if the `UseSeeding` method is not implemented. +> is called from the method, and is called from the method. When using this feature, it is recommended to implement both and methods using similar logic, even if the code using EF is asynchronous. EF Core tooling currently relies on the synchronous version of the method and will not seed the database correctly if the method is not implemented. ## Custom initialization logic -A straightforward and powerful way to perform data seeding is to use [`DbContext.SaveChangesAsync()`](xref:core/saving/index) before the main application logic begins execution. It is recommended to use `UseSeeding` and `UseAsyncSeeding` for that purpose, however sometimes using these methods is not a good solution. An example scenario is when seeding requires using two different contexts in one transaction. Below is a code sample performing custom initialization in the application directly: +A straightforward and powerful way to perform data seeding is to use before the main application logic begins execution. It is recommended to use and for that purpose, however sometimes using these methods is not a good solution. An example scenario is when seeding requires using two different contexts in one transaction. Below is a code sample performing custom initialization in the application directly: [!code-csharp[Main](../../../samples/core/Modeling/DataSeeding/Program.cs?name=CustomSeeding)] @@ -85,10 +85,10 @@ Once the data has been added to the model, [migrations](xref:core/managing-schem > [!TIP] > If you need to apply migrations as part of an automated deployment you can [create a SQL script](xref:core/managing-schemas/migrations/applying#sql-scripts) that can be previewed before execution. -Alternatively, you can use `context.Database.EnsureCreatedAsync()` to create a new database containing the managed data, for example for a test database or when using the in-memory provider or any non-relational database. Note that if the database already exists, `EnsureCreatedAsync()` will neither update the schema nor managed data in the database. For relational databases you shouldn't call `EnsureCreatedAsync()` if you plan to use Migrations. +Alternatively, you can use to create a new database containing the managed data, for example for a test database or when using the in-memory provider or any non-relational database. Note that if the database already exists, will neither update the schema nor managed data in the database. For relational databases you shouldn't call if you plan to use Migrations. > [!NOTE] -> Populating the database using the `HasData` method used to be referred to as "data seeding". This naming sets incorrect expectations, as the feature has a number of limitations and is only appropriate for specific types of data. That is why we decided to rename it to "model managed data". `UseSeeding` and `UseAsyncSeeding` methods should be used for general purpose data seeding. +> Populating the database using the method used to be referred to as "data seeding". This naming sets incorrect expectations, as the feature has a number of limitations and is only appropriate for specific types of data. That is why we decided to rename it to "model managed data". and methods should be used for general purpose data seeding. ### Limitations of model managed data @@ -99,7 +99,7 @@ This type of data is managed by migrations and the script to update the data tha Therefore this feature is most useful for static data that's not expected to change outside of migrations and does not depend on anything else in the database, for example ZIP codes. -If your scenario includes any of the following it is recommended to use `UseSeeding` and `UseAsyncSeeding` methods described in the first section: +If your scenario includes any of the following it is recommended to use and methods described in the first section: * Temporary data for testing * Data that depends on database state @@ -113,6 +113,6 @@ If your scenario includes any of the following it is recommended to use `UseSeed ## Manual migration customization -When a migration is added the changes to the data specified with `HasData` are transformed to calls to `InsertData()`, `UpdateData()`, and `DeleteData()`. One way of working around some of the limitations of `HasData` is to manually add these calls or [custom operations](xref:core/managing-schemas/migrations/operations) to the migration instead. +When a migration is added the changes to the data specified with are transformed to calls to `InsertData()`, `UpdateData()`, and `DeleteData()`. One way of working around some of the limitations of is to manually add these calls or [custom operations](xref:core/managing-schemas/migrations/operations) to the migration instead. [!code-csharp[CustomInsert](../../../samples/core/Modeling/DataSeeding/Migrations/20241016041555_Initial.cs?name=CustomInsert)] diff --git a/entity-framework/core/providers/cosmos/querying.md b/entity-framework/core/providers/cosmos/querying.md index 089a75e315..c3fbe2b7ea 100644 --- a/entity-framework/core/providers/cosmos/querying.md +++ b/entity-framework/core/providers/cosmos/querying.md @@ -144,7 +144,7 @@ foreach (var session in firstPage.Values) } ``` -Rather than terminating the LINQ query with `ToListAsync` or similar, we use the `ToPageAsync` method, instructing it to get at most 10 items in every page (note that there may be fewer items in the database). Since this is our first query, we'd like to get results from the beginning, and pass `null` as the continuation token. `ToPageAsync` returns a `CosmosPage`, which exposes a continuation token and the values in the page (up to 10 items). Your program will typically send those values to the client, along with the continuation token; this will allow resuming the query later and fetching more results. +Rather than terminating the LINQ query with `ToListAsync` or similar, we use the method, instructing it to get at most 10 items in every page (note that there may be fewer items in the database). Since this is our first query, we'd like to get results from the beginning, and pass `null` as the continuation token. returns a , which exposes a continuation token and the values in the page (up to 10 items). Your program will typically send those values to the client, along with the continuation token; this will allow resuming the query later and fetching more results. Let's assume the user now clicks on the "Next" button in their UI, asking for the next 10 items. You can then execute the query as follows: @@ -164,7 +164,7 @@ To learn more about pagination in Azure Cosmos DB, [see this page](/azure/cosmos > [!NOTE] > Azure Cosmos DB does not support backwards pagination, and does not provide a count of the total pages or items. > -> `ToPageAsync` is currently annotated as experimental, since it may be replaced with a more generic EF pagination API that isn't Azure Cosmos DB specific. Although using the current API will generate a compilation warning (`EF9102`), doing so should be safe - future changes may require minor tweaks in the API shape. +> is currently annotated as experimental, since it may be replaced with a more generic EF pagination API that isn't Azure Cosmos DB specific. Although using the current API will generate a compilation warning (`EF9102`), doing so should be safe - future changes may require minor tweaks in the API shape. ## `FindAsync` @@ -209,7 +209,7 @@ FROM ( ) s ``` -Note that `FromSql` was introduced in EF 9.0. In previous versions, `FromSqlRaw` can be used instead, although note that that method is vulnerable to SQL injection attacks. +Note that was introduced in EF 9.0. In previous versions, can be used instead, although note that that method is vulnerable to SQL injection attacks. For more information on SQL querying, see the [relational documentation on SQL queries](xref:core/querying/sql-queries); most of that content is relevant for the Azure Cosmos DB provider as well. @@ -300,15 +300,15 @@ stringValue.TrimStart() | [LTRIM(@stri .NET | SQL | Added in --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----- -EF.Functions.VectorDistance(vector1, vector2). | [VectorDistance(vector1, vector2)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 -EF.Functions.VectorDistance(vector1, vector2, bruteForce) | [VectorDistance(vector1, vector2, bruteForce)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 -EF.Functions.VectorDistance(vector1, vector2, bruteForce, distanceFunction) | [VectorDistance(vector1, vector2, bruteForce, distanceFunction)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 -EF.Functions.FullTextContains(property, keyword) | [FullTextContains(property, keyword)](/azure/cosmos-db/nosql/query/fulltextcontains) | EF 10 -EF.Functions.FullTextContainsAll(property, keyword1, keyword2) | [FullTextContainsAll(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextcontainsall) | EF 10 -EF.Functions.FullTextContainsAny(property, keyword1, keyword2) | [FullTextContainsAny(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextcontainsany) | EF 10 -EF.Functions.FullTextScore(property, keyword1, keyword2) | [FullTextScore(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextscore) | EF 10 -EF.Functions.Rrf(search1, search2) | [RRF(property, search1, search2)](/azure/cosmos-db/nosql/query/rrf). | EF 10 -EF.Functions.Rrf(new[] { search1, search2 }, weights) | [RRF(property, search1, search2, weights)](/azure/cosmos-db/nosql/query/rrf) | EF 10 +(vector1, vector2). | [VectorDistance(vector1, vector2)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 +(vector1, vector2, bruteForce) | [VectorDistance(vector1, vector2, bruteForce)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 +(vector1, vector2, bruteForce, distanceFunction) | [VectorDistance(vector1, vector2, bruteForce, distanceFunction)](/azure/cosmos-db/nosql/query/vectordistance) | EF 9 +(property, keyword) | [FullTextContains(property, keyword)](/azure/cosmos-db/nosql/query/fulltextcontains) | EF 10 +(property, keyword1, keyword2) | [FullTextContainsAll(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextcontainsall) | EF 10 +(property, keyword1, keyword2) | [FullTextContainsAny(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextcontainsany) | EF 10 +(property, keyword1, keyword2) | [FullTextScore(property, keyword1, keyword2)](/azure/cosmos-db/nosql/query/fulltextscore) | EF 10 +(search1, search2) | [RRF(property, search1, search2)](/azure/cosmos-db/nosql/query/rrf). | EF 10 +(new[] { search1, search2 }, weights) | [RRF(property, search1, search2, weights)](/azure/cosmos-db/nosql/query/rrf) | EF 10 For more information on vector search, see [the documentation](xref:core/providers/cosmos/vector-search). For more information on full-text search, see [the documentation](xref:core/providers/cosmos/full-text-search). @@ -317,7 +317,7 @@ For more information on vector search, see [the documentation](xref:core/provide .NET | SQL | Added in --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----- collection.Contains(item) | @item IN @collection -EF.Functions.CoalesceUndefined(x, y)1 | [x ?? y](/azure/cosmos-db/nosql/query/ternary-coalesce-operators#coalesce-operator) | EF 9 -EF.Functions.IsDefined(x) | [IS_DEFINED(x)](/azure/cosmos-db/nosql/query/is-defined) | EF 9 +(x, y)1 | [x ?? y](/azure/cosmos-db/nosql/query/ternary-coalesce-operators#coalesce-operator) | EF 9 +(x) | [IS_DEFINED(x)](/azure/cosmos-db/nosql/query/is-defined) | EF 9 -1 Note that `EF.Functions.CoalesceUndefined` coalesces `undefined`, not `null`. To coalesce `null`, use the regular C# `??` operator. +1 Note that coalesces `undefined`, not `null`. To coalesce `null`, use the regular C# `??` operator. diff --git a/entity-framework/core/providers/sqlite/value-generation.md b/entity-framework/core/providers/sqlite/value-generation.md new file mode 100644 index 0000000000..f25342c037 --- /dev/null +++ b/entity-framework/core/providers/sqlite/value-generation.md @@ -0,0 +1,48 @@ +--- +title: SQLite Database Provider - Value Generation - EF Core +description: Value Generation Patterns Specific to the SQLite Entity Framework Core Database Provider +author: AndriySvyryd +ms.date: 09/26/2025 +uid: core/providers/sqlite/value-generation +--- +# SQLite Value Generation + +This page details value generation configuration and patterns that are specific to the SQLite provider. It's recommended to first read [the general page on value generation](xref:core/modeling/generated-properties). + +## AUTOINCREMENT columns + +By convention, numeric primary key columns that are configured to have their values generated on add are set up with [SQLite's AUTOINCREMENT feature](https://sqlite.org/autoinc.html). Starting with EF Core 10, SQLite AUTOINCREMENT can also be enabled or disabled via configuration. + +### Configuring AUTOINCREMENT + +By convention, integer primary keys are automatically configured with AUTOINCREMENT when they are not part of a composite key and don't have a foreign key on them. However, you may need to explicitly configure a property to use SQLite AUTOINCREMENT when the property has a value conversion from a non-integer type, or when overriding conventions: + +[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteAutoincrementWithValueConverter.cs?name=SqliteAutoincrementWithValueConverter&highlight=4)] + +## Disabling AUTOINCREMENT for default SQLite value generation + +AUTOINCREMENT imposes extra CPU, memory, disk space, and disk I/O overhead compared to the default key generation algorithm in SQLite - [ROWID](https://sqlite.org/lang_createtable.html#rowid). The downside of `ROWID` is that it reuses values from deleted rows. If your scenario wouldn't be affected by this, you may want to disable AUTOINCREMENT and use SQLite's default value generation behavior instead. You can do this using the Metadata API: + + +[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteValueGenerationStrategyNone.cs?name=SqliteValueGenerationStrategyNone&highlight=5)] + +Alternatively, you can configure EF to not treat the property as value-generated: + + +[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteValueGeneratedNever.cs?name=SqliteValueGeneratedNever&highlight=5)] + +This means that it's up to the application to supply a value for the property before saving to the database. Note that this still won't disable the default value generation server-side, so non-EF usages could still get a generated value. To [completely disable value generation](https://sqlite.org/lang_createtable.html#rowids_and_the_integer_primary_key), change the column type from `INTEGER` to `INT`. diff --git a/entity-framework/core/testing/choosing-a-testing-strategy.md b/entity-framework/core/testing/choosing-a-testing-strategy.md index 5c48aa0e48..371997f0e2 100644 --- a/entity-framework/core/testing/choosing-a-testing-strategy.md +++ b/entity-framework/core/testing/choosing-a-testing-strategy.md @@ -21,7 +21,7 @@ However, tests which pass against a test double don't guarantee that your progra Because of the above difficulties with testing against a real database, developers are frequently urged to use test doubles first, and have a robust test suite which they can run frequently on their machines; tests involving the database, in contrast, are supposed to be executed much less frequently, and in many cases also provide far less coverage. We recommend giving more thought to the latter, and suggest that databases may actually be far less affected by the above problems than people tend to think: -1. Most databases can nowadays be easily installed on the developer's machine. Container-based technologies such as Docker can make this very easy, and libraries like [Testcontainers](https://testcontainers.com/modules/dotnet/) can help automate the lifecycle of containerized databases in your tests. Technologies such as [GitHub Workspaces](https://docs.github.com/en/codespaces/overview) and [Dev Container](https://code.visualstudio.com/docs/remote/create-dev-container) set up your entire development environment for you (including the database). When using SQL Server, it's also possible to test against [LocalDB](/sql/database-engine/configure-windows/sql-server-express-localdb) on Windows, or easily set up a Docker image on Linux. +1. Most databases can nowadays be easily installed on the developer's machine. Container-based technologies such as Docker can make this very easy, and libraries like [Testcontainers](https://dotnet.testcontainers.org/) can help automate the lifecycle of containerized databases in your tests. Technologies such as [GitHub Workspaces](https://docs.github.com/en/codespaces/overview) and [Dev Container](https://code.visualstudio.com/docs/remote/create-dev-container) set up your entire development environment for you (including the database). When using SQL Server, it's also possible to test against [LocalDB](/sql/database-engine/configure-windows/sql-server-express-localdb) on Windows, or easily set up a Docker image on Linux. 2. Testing against a local database - with a reasonable test dataset - is usually extremely fast: communication is completely local, and test data is typically buffered in memory on the database side. EF Core itself contains over 30,000 tests against SQL Server alone; these complete reliably in a few minutes, execute in CI on every single commit, and are very frequently executed by developers locally. Some developers turn to an in-memory database (a "fake") in the belief that this is needed for speed - this is almost never actually the case. 3. Isolation is indeed a hurdle when running tests against a real database, as tests may modify data and interfere with one another. However, there are various techniques to provide isolation in database testing scenarios; we concentrate on these in [Testing against your production database system](xref:core/testing/testing-with-the-database)). diff --git a/entity-framework/core/testing/testing-with-the-database.md b/entity-framework/core/testing/testing-with-the-database.md index a78168e93c..fe33124490 100644 --- a/entity-framework/core/testing/testing-with-the-database.md +++ b/entity-framework/core/testing/testing-with-the-database.md @@ -16,7 +16,7 @@ The main hurdle with testing which involves a real database is to ensure proper ## Setting up your database system -Most database systems nowadays can be easily installed, both in CI environments and on developer machines. While it's frequently easy enough to install the database via the regular installation mechanism, ready-to-use Docker images are available for most major databases and can make installation particularly easy in CI. Libraries like [Testcontainers](https://testcontainers.com/modules/dotnet/) can further simplify this by automatically managing containerized database instances during testing. For the developer environment, [GitHub Workspaces](https://docs.github.com/en/codespaces/overview), [Dev Container](https://code.visualstudio.com/docs/remote/create-dev-container) can set up all needed services and dependencies - including the database. While this requires an initial investment in setup, once that's done you have a working testing environment and can concentrate on more important things. +Most database systems nowadays can be easily installed, both in CI environments and on developer machines. While it's frequently easy enough to install the database via the regular installation mechanism, ready-to-use Docker images are available for most major databases and can make installation particularly easy in CI. Libraries like [Testcontainers](https://dotnet.testcontainers.org/) can further simplify this by automatically managing containerized database instances during testing. For the developer environment, [GitHub Workspaces](https://docs.github.com/en/codespaces/overview), [Dev Container](https://code.visualstudio.com/docs/remote/create-dev-container) can set up all needed services and dependencies - including the database. While this requires an initial investment in setup, once that's done you have a working testing environment and can concentrate on more important things. In certain cases, databases have a special edition or version which can be helpful for testing. When using SQL Server, [LocalDB](/sql/database-engine/configure-windows/sql-server-express-localdb) can be used to run tests locally with virtually no setup at all, spinning up the database instance on demand and possibly saving resources on less powerful developer machines. However, LocalDB is not without its issues: diff --git a/entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md index fc733cc598..56ad433bcb 100644 --- a/entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md @@ -346,7 +346,7 @@ This prevents data corruption that could occur when multiple properties are unin #### Mitigations -If you need multiple properties to share the same column, configure them explicitly: +If you need multiple properties to share the same column, configure them explicitly using and : ```c# modelBuilder.Entity(b => @@ -374,7 +374,7 @@ This provides better column name uniqueness and makes it clearer which property #### Mitigations -If you need to maintain the old column names, configure them explicitly: +If you need to maintain the old column names, configure them explicitly using and : ```c# modelBuilder.Entity() @@ -425,7 +425,7 @@ Previously, methods on `IRelationalCommandDiagnosticsLogger` such as `CommandRea #### New behavior -Starting with EF Core 10.0, these methods now require an additional `logCommandText` parameter. This parameter contains the SQL command text that will be logged, which may have sensitive data redacted when is not enabled. +Starting with EF Core 10.0, these methods now require an additional `logCommandText` parameter. This parameter contains the SQL command text that will be logged, which may have sensitive data redacted when is not enabled. #### Why diff --git a/entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md index 1a8cd86158..43996e7037 100644 --- a/entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md @@ -39,7 +39,7 @@ public class Blog } ``` -Then, insert embedding data by populating the Embedding property and calling `SaveChangesAsync()` as usual: +Then, insert embedding data by populating the Embedding property and calling as usual: ```c# IEmbeddingGenerator> embeddingGenerator = /* Set up your preferred embedding generator */; @@ -53,7 +53,7 @@ context.Blogs.Add(new Blog await context.SaveChangesAsync(); ``` -Finally, use the [`EF.Functions.VectorDistance()`](/sql/t-sql/functions/vector-distance-transact-sql) function in your LINQ queries to perform similarity search for a given user query: +Finally, use the [function](/sql/t-sql/functions/vector-distance-transact-sql) in your LINQ queries to perform similarity search for a given user query: ```c# var sqlVector = /* some user query which we should search for similarity */; @@ -71,7 +71,7 @@ For more information on vector search, [see the documentation](xref:core/provide EF 10 also fully supports the new [json data type](/sql/t-sql/data-types/json-data-type), also available on Azure SQL Database and on SQL Server 2025. While SQL Server has included JSON functionality for several versions, the data itself was stored in plain textual columns in the database; the new data type provides significant efficiency improvements and a safer way to store and interact with JSON. -With EF 10, if you've configured EF with `UseAzureSql()` or with a compatibility level of 170 or higher (SQL Server 2025), EF automatically defaults to using the new JSON data type. For example, the following entity type has a primitive collection (Tags, an array of strings) and Details (mapped as a complex type): +With EF 10, if you've configured EF with or with a compatibility level of 170 or higher (SQL Server 2025), EF automatically defaults to using the new JSON data type. For example, the following entity type has a primitive collection (Tags, an array of strings) and Details (mapped as a complex type): ```c# public class Blog @@ -126,7 +126,7 @@ Note that if your EF application already uses JSON via `nvarchar` columns, these ### Custom default constraint names -EF 10 now allows you to specify a name for default constraints, rather than letting the database generate them: +EF 10 now allows you to specify a name for default constraints using , rather than letting the database generate them: ```c# protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -137,7 +137,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } ``` -You can also enable automatic naming by EF of all default constraints: +You can also enable automatic naming by EF of all default constraints using : ```c# protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -185,19 +185,19 @@ public class BloggingContext } ``` -Once the model is configured, we can use full-text search operations in queries using methods provided in `EF.Functions`: +Once the model is configured, we can use full-text search operations in queries using methods provided in : ```c# var cosmosBlogs = await context.Blogs.Where(x => EF.Functions.FullTextContains(x.Contents, "cosmos")).ToListAsync(); ``` -The following full-text operations are currently supported: [`FullTextContains`](/azure/cosmos-db/nosql/query/fulltextcontains), [`FullTextContainsAll`](/azure/cosmos-db/nosql/query/fulltextcontainsall), [`FullTextContainsAny`](/azure/cosmos-db/nosql/query/fulltextcontainsany), [`FullTextScore`](/azure/cosmos-db/nosql/query/fulltextscore). +The following full-text operations are currently supported: , , , . See the Azure Cosmos DB documentation for details: [`FullTextContains`](/azure/cosmos-db/nosql/query/fulltextcontains), [`FullTextContainsAll`](/azure/cosmos-db/nosql/query/fulltextcontainsall), [`FullTextContainsAny`](/azure/cosmos-db/nosql/query/fulltextcontainsany), [`FullTextScore`](/azure/cosmos-db/nosql/query/fulltextscore). For more information on Cosmos full-text search, see the [documentation](xref:core/providers/cosmos/full-text-search). ### Hybrid search -EF Core now supports [`RRF`](/azure/cosmos-db/nosql/query/rrf) (Reciprocal Rank Fusion) function, which combines vector similarity search and full-text search (i.e. hybrid search). Here is an example query using hybrid search: +EF Core now supports ([Reciprocal Rank Fusion](/azure/cosmos-db/nosql/query/rrf)) function, which combines vector similarity search and full-text search (i.e. hybrid search). Here is an example query using hybrid search: ```c# float[] myVector = /* generate vector data from text, image, etc. */ @@ -309,7 +309,7 @@ CREATE TABLE [Customers] ( ); ``` -Unlike table splitting, JSON mapping allows collections within the mapped type. You can query and update properties inside your JSON documents just like any other non-JSON property, and perform efficient bulk updating on them via `ExecuteUpdateAsync` ([see release note](#execute-update-json)). +Unlike table splitting, JSON mapping allows collections within the mapped type. You can query and update properties inside your JSON documents just like any other non-JSON property, and perform efficient bulk updating on them via ([see release note](#execute-update-json)). ### Struct support @@ -338,7 +338,7 @@ customer.BillingAddress = customer.ShippingAddress; await context.SaveChangesAsync(); // ERROR ``` -In contrast, since complex types have value semantics, assigning them simply copies their properties over, as expected. For the same reasons, bulk assignment of owned entity types is not supported, whereas complex types fully support `ExecuteUpdateAsync` in EF 10 ([see release note](#execute-update-json)). +In contrast, since complex types have value semantics, assigning them simply copies their properties over, as expected. For the same reasons, bulk assignment of owned entity types is not supported, whereas complex types fully support in EF 10 ([see release note](#execute-update-json)). Similarly, comparing a customer's shipping and billing addresses in LINQ queries does not work as expected, since entity types are compared by their identities; complex types, on the other hand, are compared by their contents, producing the expected result. @@ -527,7 +527,7 @@ ORDER BY [b0].[Name], [b0].[Id] > [!NOTE] > ExecuteUpdate support for JSON requires mapping your types as complex types ([see above](#json)), and does not work when your types are mapped as owned entities. -Although EF has support JSON columns for some time and allows updating them via `SaveChanges`, `ExecuteUpdate` lacked support for them. EF10 now allows referencing JSON columns and properties within them in `ExecuteUpdate`, allowing efficient bulk updating of document-modeled data within relational databases. +Although EF has support JSON columns for some time and allows updating them via , lacked support for them. EF10 now allows referencing JSON columns and properties within them in , allowing efficient bulk updating of document-modeled data within relational databases. For example, given the following model, mapping the `BlogDetails` type to a complex JSON column in the database: @@ -551,7 +551,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } ``` -You can now use `ExecuteUpdate` as usual, referencing properties within `BlogDetails`: +You can now use as usual, referencing properties within `BlogDetails`: ```c# await context.Blogs.ExecuteUpdateAsync(s => @@ -637,7 +637,7 @@ Thanks to [@aradalvand](https://github.com/aradalvand) for proposing and pushing ### Redact inlined constants from logging by default -When logging executed SQL, EF does not log parameter values by default, since these may contain sensitive or personally-identifiable information (PII); can be used to enable logging parameter values in diagnostic or debugging scenarios ([see documentation](xref:core/logging-events-diagnostics/extensions-logging#sensitive-data)). +When logging executed SQL, EF does not log parameter values by default, since these may contain sensitive or personally-identifiable information (PII); can be used to enable logging parameter values in diagnostic or debugging scenarios ([see documentation](xref:core/logging-events-diagnostics/extensions-logging#sensitive-data)). However, EF sometimes inlines parameters into the SQL statement rather than sending them separately; in those scenarios, the potentially sensitive values were logged. EF10 no longer does this, redacting such inlined parameters by default and replacing them with a question mark character (`?`). For example, let's say we have a function that accepts a list of roles, and returns the list of users which have one of those roles: @@ -669,7 +669,7 @@ FROM [Blogs] AS [b] WHERE [b].[Role] IN (?, ?) ``` -If the roles represent sensitive information, this prevents that information from leaking into the application logs. As with regular parameters, full logging can be reenabled via . +If the roles represent sensitive information, this prevents that information from leaking into the application logs. As with regular parameters, full logging can be reenabled via . ### Warn for string concatenation with raw SQL APIs @@ -687,6 +687,7 @@ If `fieldName` is trusted or has been properly sanitized, the warning can be saf ## Other improvements +- AUTOINCREMENT can now be disabled for SQLite and is also supported for properties with value converters. For more information, see [SQLite Value Generation](xref:core/providers/sqlite/value-generation). - Stop spanning all migrations with a single transaction ([#35096](https://github.com/dotnet/efcore/issues/35096)). This reverts a change done in EF9 which caused issues in various migration scenarios. - Make SQL Server scaffolding compatible with Azure Data Explorer ([#34832](https://github.com/dotnet/efcore/pull/34832), contributed by [@barnuri](https://github.com/barnuri)). - Associate the DatabaseRoot with the scoped options instance and not the singleton options ([#34477](https://github.com/dotnet/efcore/pull/34477), contributed by [@koenigst](https://github.com/koenigst)). diff --git a/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md index 95795d99fd..4ff9378494 100644 --- a/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md @@ -627,19 +627,50 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) #### Old behavior -Previously, when multiple calls to `AddDbContext`, `AddDbContextPool`, `AddDbContextFactory` or `AddPooledDbContextFactor` were made with the same context type but conflicting configuration, the first one won. +Previously, when multiple calls to `AddDbContext`, `AddDbContextPool`, `AddDbContextFactory` or `AddPooledDbContextFactory` were made with the same context type but conflicting configuration, the first one won. #### New behavior -Starting with EF Core 8.0, the configuration from the last call one will take precedence. +Starting with EF Core 8.0, the configuration from the last call will take precedence. #### Why -This was changed to be consistent with the new method `ConfigureDbContext` that can be used to add configuration either before or after the `Add*` methods. +This was changed to be consistent with the new method `ConfigureDbContext`, that enables configuration composability for non-conflicting configurations. See [DbContext configuration](xref:core/dbcontext-configuration/index#configuredbcontext) for more information. #### Mitigations -Reverse the order of `Add*` calls. +If your application depends on the previous behavior where the first registration wins, you have several options: + +1. **Reorder your registrations**: Place the registration with the configuration you want to use last: + + ```csharp + services.AddDbContext(options => + options.UseSqlServer("connection1")); // This will be ignored now + + services.AddDbContext(options => + options.UseSqlServer("connection2")); // This will be used + ``` + +2. **Remove previous registrations**: If possible, remove the conflicting registration. + +3. **Use conditional registration**: Check if the service is already registered before adding: + + ```csharp + if (!services.Any(d => d.ServiceType == typeof(DbContextOptions))) + { + services.AddDbContext(options => + options.UseSqlServer("connection")); + } + ``` + +4. **Use the new `ConfigureDbContext` method**: This allows you to configure options without registering the context itself. See [DbContext configuration](xref:core/dbcontext-configuration/index#configuredbcontext) for more information: + + ```csharp + services.ConfigureDbContext(options => + options.UseSqlServer("connection")); + + services.AddDbContext(); // Register the context without configuration + ``` diff --git a/entity-framework/core/what-is-new/ef-core-9.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-9.0/breaking-changes.md index 459cea6c47..e3c7a8156b 100644 --- a/entity-framework/core/what-is-new/ef-core-9.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-9.0/breaking-changes.md @@ -44,11 +44,11 @@ EF Core 9 targets .NET 8. This means that existing applications that target .NET #### Old behavior -If the model has pending changes compared to the last migration they are not applied with the rest of the migrations when `Migrate` is called. +If the model has pending changes compared to the last migration they are not applied with the rest of the migrations when is called. #### New behavior -Starting with EF Core 9.0, if the model has pending changes compared to the last migration an exception is thrown when `dotnet ef database update`, `Migrate` or `MigrateAsync` is called: +Starting with EF Core 9.0, if the model has pending changes compared to the last migration an exception is thrown when `dotnet ef database update`, or is called: > :::no-loc text="The model for context 'DbContext' has pending changes. Add a new migration before updating the database. This exception can be suppressed or logged by passing event ID 'RelationalEventId.PendingModelChangesWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'."::: #### Why @@ -60,16 +60,16 @@ Forgetting to add a new migration after making model changes is a common mistake There are several common situations when this exception can be thrown: - There are no migrations at all. This is common when the database is updated through other means. - - **Mitigation**: If you don't plan to use migrations for managing the database schema then remove the `Migrate` or `MigrateAsync` call, otherwise add a migration. + - **Mitigation**: If you don't plan to use migrations for managing the database schema then remove the or call, otherwise add a migration. - There is at least one migration, but the model snapshot is missing. This is common for migrations created manually. - **Mitigation**: Add a new migration using EF tooling, this will update the model snapshot. -- The model wasn't modified by the developer, but it's built in a non-deterministic way causing EF to detect it as modified. This is common when `new DateTime()`, `DateTime.Now`, `DateTime.UtcNow`, or `Guid.NewGuid()` are used in objects supplied to `HasData()`. - - **Mitigation**: Add a new migration, examine its contents to locate the cause, and replace the dynamic data with a static, hardcoded value in the model. The migration should be recreated after the model is fixed. If dynamic data has to be used for seeding consider using [the new seeding pattern](/ef/core/what-is-new/ef-core-9.0/whatsnew#improved-data-seeding) instead of `HasData()`. +- The model wasn't modified by the developer, but it's built in a non-deterministic way causing EF to detect it as modified. This is common when `new DateTime()`, `DateTime.Now`, `DateTime.UtcNow`, or `Guid.NewGuid()` are used in objects supplied to . + - **Mitigation**: Add a new migration, examine its contents to locate the cause, and replace the dynamic data with a static, hardcoded value in the model. The migration should be recreated after the model is fixed. If dynamic data has to be used for seeding consider using [the new seeding pattern](/ef/core/what-is-new/ef-core-9.0/whatsnew#improved-data-seeding) instead of . - The last migration was created for a different provider than the one used to apply the migrations. - **Mitigation**: This is an unsupported scenario. The warning can be suppressed using the code snippet below, but this scenario will likely stop working in a future EF Core release. The recommended solution is [to generate a separate set of migrations for each provider](xref:core/managing-schemas/migrations/providers). - The migrations are generated, modified or chosen dynamically by replacing some of the EF services. - **Mitigation**: The warning is a false positive in this case and should be suppressed: - `options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))` + `options.ConfigureWarnings(w => w.Ignore())` - You are using ASP.NET Core Identity and change options that affect the model, such as: ```csharp @@ -136,7 +136,7 @@ await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () => #### New behavior -Starting with EF Core 9.0, `Migrate` and `MigrateAsync` calls will start a transaction and execute the commands using an `ExecutionStrategy` and if your app uses the above pattern an exception is thrown: +Starting with EF Core 9.0, and calls will start a transaction and execute the commands using an `ExecutionStrategy` and if your app uses the above pattern an exception is thrown: > :::no-loc text="An error was generated for warning 'Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning': A transaction was started before applying migrations. This prevents a database lock to be acquired and hence the database will not be protected from concurrent migration applications. The transactions and execution strategy are already managed by EF as needed. Remove the external transaction. This exception can be suppressed or logged by passing event ID 'RelationalEventId.MigrationsUserTransactionWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'."::: #### Why @@ -371,7 +371,7 @@ An emerging JSON practice uses a `$type` property in scenarios where a document' ##### Mitigations -The easiest mitigation is to simply configure the name of the discriminator property to be `Discriminator`, just as before: +The easiest mitigation is to simply configure the name of the discriminator property to be `Discriminator`, just as before using : ```csharp modelBuilder.Entity().HasDiscriminator("Discriminator"); @@ -403,7 +403,7 @@ EF 9.0 generally changed the mapping to be more aligned with common Azure Cosmos ##### Mitigations -The easiest mitigation is to simply configure EF to include the discriminator in the JSON `id` property, as before. A new configuration option has been introduced for this purpose: +The easiest mitigation is to simply configure EF to include the discriminator in the JSON `id` property, as before using . A new configuration option has been introduced for this purpose: ```csharp modelBuilder.Entity().HasDiscriminatorInJsonId(); @@ -433,13 +433,13 @@ EF 9.0 generally changed the mapping to be more aligned with common Azure Cosmos ##### Mitigations -If you would like to preserve EF Core 8 behavior the easiest mitigation is to use a new configuration option that has been introduced for this purpose: +If you would like to preserve EF Core 8 behavior the easiest mitigation is to use , a new configuration option that has been introduced for this purpose: ```csharp modelBuilder.Entity().HasShadowId(); ``` -Doing this for all your top-level entity types will make EF behave just like before. Or you could apply it to all entity types in the model with one call: +Doing this for all your top-level entity types will make EF behave just like before. Or you could apply it to all entity types in the model with one call using : ```csharp modelBuilder.HasShadowIds(); diff --git a/entity-framework/core/what-is-new/ef-core-9.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-9.0/whatsnew.md index dd6003db2b..e2b9b4403a 100644 --- a/entity-framework/core/what-is-new/ef-core-9.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-9.0/whatsnew.md @@ -153,7 +153,7 @@ In EF 9.0, the LINQ translation capabilities of the the Azure Cosmos DB provider * Support for aggregate operators such as `Count` and `Sum`. * Additional function translations (see the [function mappings documentation](xref:core/providers/cosmos/querying#function-mappings) for the full list of supported translations): * Translations for `DateTime` and `DateTimeOffset` component members (`DateTime.Year`, `DateTimeOffset.Month`...). - * `EF.Functions.IsDefined` and `EF.Functions.CoalesceUndefined` now allow dealing with `undefined` values. + * and now allow dealing with `undefined` values. * `string.Contains`, `StartsWith` and `EndsWith` now support `StringComparison.OrdinalIgnoreCase`. For the full list of querying improvements, see [this issue](https://github.com/dotnet/efcore/issues/33033): @@ -229,7 +229,7 @@ public class BloggingContext } ``` -Once that's done, use the `EF.Functions.VectorDistance()` function in LINQ queries to perform vector similarity search: +Once that's done, use the function in LINQ queries to perform vector similarity search: ```c# var blogs = await context.Blogs @@ -256,7 +256,7 @@ foreach (var post in page.Values) } ``` -The new `ToPageAsync` operator returns a `CosmosPage`, which exposes a continuation token that can be used to efficiently resume the query at a later point, fetching the next 10 items: +The new operator returns a , which exposes a continuation token that can be used to efficiently resume the query at a later point, fetching the next 10 items: ```c# var nextPage = await context.Sessions.OrderBy(s => s.Id).ToPageAsync(10, continuationToken); @@ -266,7 +266,7 @@ For more information, [see the documentation section on pagination](xref:core/pr ### FromSql for safer SQL querying -The Azure Cosmos DB provider has allowed SQL querying via . However, that API can be susceptible to SQL injection attacks when user-provided data is interpolated or concatenated into the SQL. In EF 9.0, you can now use the new `FromSql` method, which always integrates parameterized data as a parameter outside the SQL: +The Azure Cosmos DB provider has allowed SQL querying via . However, that API can be susceptible to SQL injection attacks when user-provided data is interpolated or concatenated into the SQL. In EF 9.0, you can now use the new method, which always integrates parameterized data as a parameter outside the SQL: ```c# var maxAngle = 8; @@ -279,7 +279,7 @@ For more information, [see the documentation section on pagination](xref:core/pr ### Role-based access -Azure Cosmos DB for NoSQL includes a [built-in role-based access control (RBAC) system](/azure/cosmos-db/role-based-access-control). This is now supported by EF9 for all data plane operations. However, Azure Cosmos DB SDK does not support RBAC for management plane operations in Azure Cosmos DB. Use Azure Management API instead of `EnsureCreatedAsync` with RBAC. +Azure Cosmos DB for NoSQL includes a [built-in role-based access control (RBAC) system](/azure/cosmos-db/role-based-access-control). This is now supported by EF9 for all data plane operations. However, Azure Cosmos DB SDK does not support RBAC for management plane operations in Azure Cosmos DB. Use Azure Management API instead of with RBAC. ### Synchronous I/O is now blocked by default @@ -367,7 +367,7 @@ GROUP BY [s].[StoreAddress_City], [s].[StoreAddress_Country], [s].[StoreAddress_ > [!TIP] > The code shown here comes from [ExecuteUpdateSample.cs](https://github.com/dotnet/EntityFramework.Docs/tree/main/samples/core/Miscellaneous/NewInEFCore9/ExecuteUpdateSample.cs). -Similarly, in EF9 `ExecuteUpdate` has also been improved to accept complex type properties. However, each member of the complex type must be specified explicitly. For example: +Similarly, in EF9 has also been improved to accept complex type properties. However, each member of the complex type must be specified explicitly. For example: