diff --git a/aspnetcore/blazor/blazor-ef-core.md b/aspnetcore/blazor/blazor-ef-core.md index 03b0ef4930ab..cd535e63103e 100644 --- a/aspnetcore/blazor/blazor-ef-core.md +++ b/aspnetcore/blazor/blazor-ef-core.md @@ -46,8 +46,6 @@ For Microsoft Azure services, we recommend using *managed identities*. Managed i The sample app was built as a reference for server-side Blazor apps that use EF Core. The sample app includes a grid with sorting and filtering, delete, add, and update operations. -The sample demonstrates use of EF Core to handle optimistic concurrency. However, [native database-generated concurrency tokens](/ef/core/saving/concurrency?tabs=fluent-api#native-database-generated-concurrency-tokens) aren't supported for SQLite databases, which is the database provider for the sample app. To demonstrate concurrency with the sample app, adopt a different database provider that supports database-generated concurrency tokens (for example, the [SQL Server provider](/ef/core/providers/sql-server)). - :::moniker range=">= aspnetcore-8.0" [View or download sample code](https://github.com/dotnet/blazor-samples) ([how to download](xref:blazor/fundamentals/index#sample-apps)): Select the folder that matches the version of .NET that you're adopting. Within the version folder, access the sample named `BlazorWebAppEFCore`. @@ -60,7 +58,58 @@ The sample demonstrates use of EF Core to handle optimistic concurrency. However :::moniker-end -The sample uses a local [SQLite](https://www.sqlite.org/index.html) database so that it can be used on any platform. The sample also configures database logging to show the SQL queries that are generated. This is configured in `appsettings.Development.json`: +### Use the sample with SQLite + +The sample uses a local [SQLite](https://www.sqlite.org/index.html) database so that it can be used on any platform. + +The sample demonstrates use of EF Core to handle optimistic concurrency. However, [native database-generated concurrency tokens](/ef/core/saving/concurrency?tabs=fluent-api#native-database-generated-concurrency-tokens) aren't supported for SQLite databases, which is the database provider for the sample app. To demonstrate concurrency with the sample app, adopt a different database provider that supports database-generated concurrency tokens (for example, the [SQL Server provider](/ef/core/providers/sql-server)). You can adopt SQL Server for the sample app by following the guidance in the next section, *Use the sample with SQL Server and optimistic concurrency*. + +### Use the sample with SQL Server and optimistic concurrency + +The sample demonstrates use of EF Core to handle optimistic concurrency but only for a database provider that uses [native database-generated concurrency tokens](/ef/core/saving/concurrency?tabs=fluent-api#native-database-generated-concurrency-tokens), which is a feature supported for SQL Server. To demonstrate concurrency with the sample app, the sample app can be converted from the SQLite provider to use the [SQL Server provider](/ef/core/providers/sql-server) with a new SQL Server database created using .NET scaffolding. + +Use the following guidance to adopt SQL Server for the sample app using Visual Studio. + +Open the `Program` file (`Program.cs`) and comment out the lines that add the database context factory with the SQLite provider: + +```diff +- builder.Services.AddDbContextFactory(opt => +- opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")); ++ //builder.Services.AddDbContextFactory(opt => ++ // opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")); +``` + +Save the `Program.cs` file. + +Right-click the project in **Solution Explorer** and select **Add** > **New Scaffolded Item**. + +In the **Add New Scaffolded Item** dialog, select **Installed** > **Common** > **Blazor** > **Razor Component** > **Razor Components Using Entity Framework (CRUD)**. Select the **Add** button. + +In the **Add Razor Components Using Entity Framework (CRUD)** dialog, use the following settings: + +* **Template**: Use the default selection (**CRUD**). +* **Model class**: Select the `Contact` model from the dropdown list. +* **DbContext class**: Select the plus sign (`+`) and select **Add** using the default context class name generated by the scaffolder. +* **Database provider**: Use the default selection (**SQL Server**). + +Select **Add** to scaffold the model and create the SQL Server database. + +When the scaffolding operation completes, delete the generated context class from the `Data` folder (`Data/{PROJECT NAME}Context.cs`, where the `{PROJECT NAME}` placeholder is the project's name/namespace). + +Delete the `ContactPages` folder from the `Components/Pages` folder, which contains [QuickGrid](xref:blazor/components/quickgrid)-based pages for contact management. For a complete demonstration of QuickGrid-based pages for managing data, use the tutorial. + +Open the `Program` file (`Program.cs`) and find the line that scaffolding added to create a database context factory using the SQL Server provider. Change the context from the generated context class (deleted earlier) to the app's existing `ContactContext` class: + +```diff +- builder.Services.AddDbContextFactory(options => ++ builder.Services.AddDbContextFactory(options => +``` + +At this point, the app is using the SQL Server provider and a SQL Server database created for the `Contact` model class. Optimistic concurrency works using [native database-generated concurrency tokens](/ef/core/saving/concurrency?tabs=fluent-api#native-database-generated-concurrency-tokens) that are already implemented in the sample app's `ContactContext` class. + +### Database logging + +The sample also configures database logging to show the SQL queries that are generated. This is configured in `appsettings.Development.json`: :::moniker range=">= aspnetcore-9.0"