如何用单个包在Blazor与Web API中统一使用Entity Framework Core
共用EF Core数据层的实现方案及Blazor上下文问题解决
一、共用EF Core数据层的可行方案
将数据层核心逻辑封装为独立类库,让Blazor和Web API直接引用,即可实现业务流程与EF Core操作的共用,具体步骤如下:
- 创建一个类库项目(如
YourApp.Data),目标框架选择.NET 6+或.NET Standard,确保兼容Blazor与Web API - 在类库中实现以下内容:
- EF Core的
DbContext(如你的SqlContext) - 实体类(
UserEntity等) - 业务服务接口(
IUserService)与实现(UserService) - DTO类及对象映射逻辑(如
UserDTO和MapTo扩展方法)
- EF Core的
- Blazor项目与Web API项目添加对该类库的引用
- 在各自项目的依赖注入容器中注册
DbContext与业务服务:- Web API中按常规注册为
Scoped(对应每个请求的生命周期) - Blazor Server中需注意
DbContext的生命周期配置,这也是你遇到数据缓存问题的核心原因
- Web API中按常规注册为
二、Blazor中DbContext缓存问题的最优解决
你遇到的问题本质是:Blazor Server中Scoped生命周期的DbContext会与组件实例绑定,长期驻留内存,导致上下文缓存了旧数据(API修改数据库后,Blazor的上下文未同步刷新)。以下是最优解决方案:
方案:基于IDbContextFactory实现上下文短生命周期
无需在每个方法重复编写上下文创建代码,只需改造服务,让每个业务方法使用独立的上下文实例:
public class UserService : IUserService { private readonly IDbContextFactory<SqlContext> _dbContextFactory; public UserService(IDbContextFactory<SqlContext> dbContextFactory) { _dbContextFactory = dbContextFactory; } public async Task Add(UserDTO userDTO, UserType Type) { using var db = _dbContextFactory.CreateDbContext(); var u = await db.Users.Where(u => u.Id == userDTO.Id).AsNoTracking().FirstOrDefaultAsync(); if (u is not null) { throw new Exception("same ID"); } userDTO.Type = Type; var entity = userDTO.MapTo<UserEntity>(); entity.Type = Type; await db.AddAsync(entity); await db.SaveChangesAsync(); } public async Task UpdatePassword(string userId, string password) { using var db = _dbContextFactory.CreateDbContext(); var user = await db.Users.SingleAsync(u => u.Id == userId); if (!string.IsNullOrEmpty(password)) { user.Password = password.ToSHA512(); } await db.SaveChangesAsync(); } }
通过using语句自动释放上下文,每个业务方法都使用全新的上下文实例,彻底避免旧数据缓存问题,同时该实现可直接在Blazor与Web API中复用。
三、额外注意事项
- 数据库连接字符串需在Blazor与Web API各自的配置文件(
appsettings.json)中单独配置,类库中的DbContext通过配置读取连接字符串 - Blazor WebAssembly不建议直接通过EF Core连接数据库(会暴露连接字符串,存在安全风险),应通过调用Web API操作数据,此时共用类库可部署在Web API端,WASM仅需调用API接口
内容的提问来源于stack exchange,提问作者lyj
相关产品推荐
相关产品推荐

