Skip to main content

managing-blazor-server-data-access

Manages data access and state in Blazor Server applications. Solves critical Blazor Server issues: Session NULL in WebSocket circuits, DbContext threading/concurrent operation errors, cart/wizard state loss, scoped lifetime issues, Session NullReferenceException. Configures IDbContextFactory for long-lived circuits (required for ANY Blazor Server app using EF Core), Session/ViewState/Application state alternatives (ProtectedSessionStorage, scoped services, database-backed), and DataSource to service injection migration. Covers Web.config to appsettings.json. Use when handling data access in Blazor Server, fixing session/DbContext/cart errors, resolving build errors for System.Data.Entity namespaces or EntityFramework package references, or troubleshooting data access failures in Blazor Server applications.

Informações da origem

Repositório
microsoft/upgrade-agent-plugins
Última atividade na origem
10 de setembro de 2026 às 04:23
Idioma detectado do SKILL.md
inglês
Estrelas
41
Forks
9

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
2 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
managing-blazor-server-data-access
description
Manages data access and state in Blazor Server applications. Solves critical Blazor Server issues: Session NULL in WebSocket circuits, DbContext threading/concurrent operation errors, cart/wizard state loss, scoped lifetime issues, Session NullReferenceException. Configures IDbContextFactory for long-lived circuits (required for ANY Blazor Server app using EF Core), Session/ViewState/Application state alternatives (ProtectedSessionStorage, scoped services, database-backed), and DataSource to service injection migration. Covers Web.config to appsettings.json. Use when handling data access in Blazor Server, fixing session/DbContext/cart errors, resolving build errors for System.Data.Entity namespaces or EntityFramework package references, or troubleshooting data access failures in Blazor Server applications.
metadata
{"discovery":"lazy","traits":".NET|CSharp|VisualBasic|DotNetCore"}
# Managing Data Access and State in Blazor Server Manages data access and state in Blazor Server applications. Covers critical Blazor Server patterns required for long-lived circuits (IDbContextFactory, Session state alternatives, shopping cart persistence). ## Related Skills **Reference guide for complementary patterns.** The workflow steps below contain explicit instructions on when to invoke each skill. | Skill | Use For | |-------|---------| | **migrating-webforms-to-blazor-server** | Initial WebForms to Blazor migration (project setup, Routes, markup conversion) | | **managing-blazor-server-authentication** | Authentication setup and patterns in Blazor Server | | **migrating-ef6-code-first-to-ef-core** | Entity Framework 6 Code-First to EF Core migration → Step 1 | | **migrating-mvc-configuration** | Web.config to appsettings.json migration → Step 4 | ## Prerequisites This skill works with any Blazor Server application. **If migrating from WebForms**, the `migrating-webforms-to-blazor-server` skill handles initial Blazor Server setup. --- ## Workflow Configure Blazor Server data and state management in order: ``` Configuration Progress: - [ ] Step 1: Set up data infrastructure (DbContext factory) - [ ] Step 2: Configure data binding (DataSource to services) - [ ] Step 3: Configure state management (Session to storage) - [ ] Step 4: Migrate configuration (Web.config to appsettings.json) ``` --- ## Step 1: Set Up Data Infrastructure ### Database Provider Detection If the Web Forms project uses Entity Framework, check `Web.config` connection strings to determine the database provider. **CRITICAL: Preserve the original database provider** - do NOT default to SQLite unless the original project specifically used it. SQL Server (including LocalDB) is the most common Web Forms database. **Detect provider from Web.config:** | Web.config Indicator | Database Provider | EF Core Package to Install | |---------------------|-------------------|----------------------------| | `providerName="System.Data.SqlClient"` | SQL Server | `Microsoft.EntityFrameworkCore.SqlServer` | | `providerName="System.Data.SQLite"` | SQLite | `Microsoft.EntityFrameworkCore.Sqlite` | | `providerName="Npgsql"` | PostgreSQL | `Npgsql.EntityFrameworkCore.PostgreSQL` | | `providerName="MySql.Data.MySqlClient"` | MySQL | `Pomelo.EntityFrameworkCore.MySql` | **Add the detected provider to your Blazor project:** ```bash # Example for SQL Server (most common) dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools ``` > **Note:** If you previously completed `migrating-webforms-to-blazor-server` Step 1, the provider packages are already installed - skip to the next section. ### Entity Framework Migration **Identify your data access pattern and execute the appropriate skill:** | Original Pattern | Skill to Execute | Returns Here? | |-----------------|------------------|---------------| | **EF6 Code-First** (no .edmx files) | `migrating-ef6-code-first-to-ef-core` | ✅ Yes | | **EDMX** (Database-First/Model-First) | `migrating-edmx-to-code-first` | ✅ Yes | | **LINQ to SQL** (System.Data.Linq) | `migrating-linq-to-sql-to-ef-core` | ✅ Yes | **All EF Core migration skills** handle: - Package swaps (legacy → Microsoft.EntityFrameworkCore) - Namespace updates - DbContext constructor changes (connection string → `DbContextOptions`) - Entity configuration conversion - API changes and migrations history ⚠️ **Critical:** Those skills use `AddDbContext` (scoped lifetime), which **does NOT work** in Blazor Server long-lived circuits. After completing any EF migration skill, **you must** apply the Blazor-specific configuration below. ### Configure DbContext for Blazor Server ⚠️ **CRITICAL: Replace** the `AddDbContext` registration from the EF migration skill with `AddDbContextFactory`: The EF migration skills use `AddDbContext` (scoped lifetime), which is correct for MVC/API but **WILL FAIL** in Blazor Server. You must replace it. **Before (from EF migration skill - DO NOT USE):** ```csharp // ❌ WRONG for Blazor Server builder.Services.AddDbContext<SchoolContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); ``` **After (Blazor Server pattern - REQUIRED):** ```csharp // ✅ CORRECT for Blazor Server — use IDbContextFactory for long-lived Blazor circuits builder.Services.AddDbContextFactory<SchoolContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // ↑ Replace with UseNpgsql(), UseMySql(), UseSqlite(), etc. to match original provider ``` **Why `IDbContextFactory`?** Blazor Server circuits are long-lived. A single `DbContext` instance would accumulate stale data and tracking issues. The factory pattern creates short-lived contexts per operation. **Verification:** After making this change, search Program.cs for `AddDbContext`. If found, you missed the replacement - it MUST be `AddDbContextFactory` for Blazor Server. ### ADO.NET (Non-EF) Data Access If the WebForms project uses **raw ADO.NET** (SqlCommand, SqlDataReader) without Entity Framework: **Execute `migrating-to-microsoft-data-sqlclient` skill** to upgrade the provider (System.Data.SqlClient → Microsoft.Data.SqlClient). This works in Blazor Server with standard DI-registered services - no IDbContextFactory needed. Example service pattern: ```csharp public class ProductRepository(IConfiguration configuration) { public async Task<List<Product>> GetProductsAsync() { using var connection = new SqlConnection(configuration.GetConnectionString("DefaultConnection")); using var command = new SqlCommand("SELECT * FROM Products", connection); await connection.OpenAsync(); // ... read data } } ``` ### Data Access Service Layer Create services to encapsulate database operations: ```csharp // ProductService.cs public class ProductService(IDbContextFactory<SchoolContext> factory) { public async Task<List<Product>> GetProductsAsync() { using var db = factory.CreateDbContext(); return await db.Products.ToListAsync(); } public async Task<Product?> GetProductAsync(int id) { using var db = factory.CreateDbContext(); return await db.Products.FindAsync(id); } } // Program.cs builder.Services.AddScoped<IProductService, ProductService>(); ``` ### Connection String Migration Before DbContext can use `GetConnectionString()`, migrate connection strings from Web.config to appsettings.json: **Web.config:** ```xml <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=MyApp;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> ``` **Create or update appsettings.json:** ```json { "ConnectionStrings": { "DefaultConnection": "Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=MyApp;Integrated Security=True" } } ``` **Key changes:** - Remove `providerName` attribute (provider specified in code via `UseSqlServer()`, etc.) - Escape backslashes: `\` → `\\` - Section name is `ConnectionStrings` (capital C and S) > **Note:** Complete configuration migration (appSettings, custom sections, secrets, environment files) will be done in Step 4. --- ## Step 2: Migrate DataSource Controls to Services Web Forms declarative `DataSource` controls (`SqlDataSource`, `ObjectDataSource`, `EntityDataSource`) have no equivalent in Blazor. Replace with dependency-injected services that load data programmatically in component lifecycle methods. ```xml <!-- Web Forms — declarative data binding --> <asp:SqlDataSource ID="ProductsDS" runat="server" ConnectionString="<%$ ConnectionStrings:DefaultConnection %>" SelectCommand="SELECT * FROM Products" /> <asp:GridView DataSourceID="ProductsDS" runat="server" /> ``` ```razor @* Blazor — service injection + @foreach table *@ @inject IProductService ProductService <table> <thead><tr><th>Name</th><th>Price</th></tr></thead> <tbody> @foreach (var p in products) { <tr> <td>@p.Name</td> <td>@p.UnitPrice.ToString("C")</td> </tr> } </tbody> </table> @code { private List<Product> products = []; protected override async Task OnInitializedAsync() { products = await ProductService.GetProductsAsync(); } } ``` > **For advanced scenarios** (sorting, filtering, pagination), use **Microsoft.AspNetCore.Components.QuickGrid** (`dotnet add package Microsoft.AspNetCore.Components.QuickGrid`). ### Service Registration Pattern ```csharp // Program.cs — use the provider that matches the original Web Forms database builder.Services.AddRazorComponents().AddInteractiveServerComponents(); builder.Services.AddDbContextFactory<ProductContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // ↑ Match the original provider: UseNpgsql(), UseMySql(), UseSqlite(), etc. builder.Services.AddScoped<IProductService, ProductService>(); builder.Services.AddScoped<ICategoryService, CategoryService>(); builder.Services.AddScoped<IOrderService, OrderService>(); // ... after builder.Build() ... app.MapRazorComponents<App>().AddInteractiveServerRenderMode(); ``` --- ## Step 3: Convert State Management Patterns > **CRITICAL:** When using `<Routes @rendermode="InteractiveServer" />` (global interactive server mode), `HttpContext.Session` is **NULL** during WebSocket rendering. Session state access inside Blazor components will throw `NullReferenceException` or silently fail. **Why:** After the initial HTTP request establishes the SignalR circuit, Blazor communicates over WebSocket. There is no HTTP request/response, and therefore no session middleware processing during component interactions. **Solution:** Replace Session state with one of four patterns based on your requirements: | Pattern | Use For | Survives Refresh? | Survives Disconnect? | |---------|---------|-------------------|----------------------| | **Option A: Minimal API Endpoints** | Form submissions, business operations | ✅ Yes | ✅ Yes (if persisted) | | **Option B: Scoped Services** | Transient UI state (wizard progress, filters) | ❌ No | ❌ No | | **Option C: Database-Backed** | Business-critical state (cart, preferences) | ✅ Yes | ✅ Yes | | **Option D: ProtectedSessionStorage** | Browser tab-specific state | ✅ Yes | ❌ No | **For detailed implementation examples and decision guidance**, read **[ref/session-state-patterns.md](ref/session-state-patterns.md)**. **Quick reference:** - Shopping carts, user preferences → **Option C** (database-backed) - Form submissions → **Option A** (minimal API endpoints) - Wizard progress, temporary filters → **Option B** (scoped services) - Tab-specific data that survives refresh → **Option D** (ProtectedSessionStorage) --- ## Step 4: Migrate Configuration Complete configuration migration from Web.config to appsettings.json. This step handles all configuration beyond the connection strings already migrated in Step 1. **Execute the `migrating-mvc-configuration` skill** to migrate: - AppSettings → appsettings.json with nested JSON structure - Additional connection strings (if your app has multiple databases) - IConfiguration injection patterns - IOptions<T> strongly-typed configuration - Environment-specific configuration files (Development, Staging, Production) - Custom config sections → POCO classes - Secrets migration to User Secrets / Key Vault - ConfigurationManager removal and cleanup Execute that skill to complete configuration migration, then return here. ### Blazor-Specific Syntax Note Configuration access in Blazor components uses `@inject` directive syntax instead of constructor injection: ```csharp // Blazor component @inject IConfiguration Configuration @inject IOptions<AppSettings> AppSettingsOptions @code { protected override void OnInitialized() { var apiUrl = Configuration["AppSettings:ApiBaseUrl"]; var maxPageSize = AppSettingsOptions.Value.MaxPageSize; } } ``` The underlying concepts (IConfiguration, IOptions<T>, registration in Program.cs) are identical to the general skill's guidance. --- ## Reference Documents For detailed implementation patterns and code examples: - **[ref/session-state-patterns.md](ref/session-state-patterns.md)** — Session state migration patterns (scoped services, database-backed, ProtectedSessionStorage, minimal API endpoints) --- ## Common Data Migration Gotchas ### DbContext Lifetime Blazor Server circuits are long-lived. Always use `IDbContextFactory` and create short-lived `DbContext` instances per operation. ⚠️ **CRITICAL VALIDATION:** After completing EF migration steps, search `Program.cs` for the pattern `AddDbContext<`. If found, you have NOT correctly applied the Blazor Server pattern - it MUST be `AddDbContextFactory<` instead. The referenced EF migration skills use `AddDbContext` (correct for MVC/API), which will cause runtime failures in Blazor Server. ### No Page-Level Transaction Scope Web Forms `SelectMethod` runs inside a page lifecycle. Blazor doesn't have this. Use explicit transaction scopes in services if needed: ```csharp using var db = factory.CreateDbContext(); using var transaction = await db.Database.BeginTransactionAsync(); // ... operations await transaction.CommitAsync(); ``` ### Async All the Way Web Forms `SelectMethod` returns `IQueryable` synchronously. Blazor services should be async: ```csharp // WRONG: return db.Products.ToList(); // RIGHT: return await db.Products.ToListAsync(); ``` ### No ConfigurationManager `ConfigurationManager.AppSettings["key"]` doesn't exist. Inject `IConfiguration` or use the Options pattern.
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub