为30+数据表实现通用CRUD操作(Blazor/.NET Core)
在Blazor中实现通用CRUD操作(基于.NET Core & C#)
针对你30多张数据表的CRUD需求,最常用且高效的方案是泛型仓储模式,通过泛型约束实现一套代码适配所有实体类型,彻底避免重复编写CRUD逻辑。
1. 定义通用仓储接口
先抽象出CRUD的核心操作,确保所有实体都遵循统一的操作规范:
public interface IRepository<T> where T : class { // 根据主键获取实体 Task<T> GetByIdAsync(object id); // 获取所有实体 Task<IEnumerable<T>> GetAllAsync(); // 添加实体 Task AddAsync(T entity); // 更新实体 Task UpdateAsync(T entity); // 删除实体 Task DeleteAsync(T entity); // 批量保存更改(可选,用于多操作统一提交) Task SaveChangesAsync(); }
2. 实现通用仓储类
基于Entity Framework Core实现接口逻辑,利用泛型自动关联对应的数据表:
using Microsoft.EntityFrameworkCore; public class Repository<T> : IRepository<T> where T : class { private readonly DbContext _dbContext; private readonly DbSet<T> _dbSet; public Repository(DbContext dbContext) { _dbContext = dbContext; _dbSet = dbContext.Set<T>(); } public async Task<T> GetByIdAsync(object id) { return await _dbSet.FindAsync(id); } public async Task<IEnumerable<T>> GetAllAsync() { return await _dbSet.ToListAsync(); } public async Task AddAsync(T entity) { await _dbSet.AddAsync(entity); await _dbContext.SaveChangesAsync(); } public async Task UpdateAsync(T entity) { _dbSet.Update(entity); await _dbContext.SaveChangesAsync(); } public async Task DeleteAsync(T entity) { _dbSet.Remove(entity); await _dbContext.SaveChangesAsync(); } public async Task SaveChangesAsync() { await _dbContext.SaveChangesAsync(); } }
3. 注册服务到依赖注入容器
在Program.cs中注册泛型仓储和你的DbContext,让Blazor可以注入使用:
var builder = WebApplication.CreateBuilder(args); // 注册DbContext(替换为你的实际DbContext类) builder.Services.AddDbContext<YourAppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 注册泛型仓储 builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); // 其他Blazor服务注册... var app = builder.Build(); // 中间件配置... app.Run();
4. 在Blazor组件中使用通用CRUD
以更新Customer实体为例,直接注入对应类型的仓储即可操作:
@page "/customer/update/{CustomerId:int}" @inject IRepository<Customer> _customerRepository @inject NavigationManager NavigationManager <h3>更新客户信息</h3> @if (_customer != null) { <input type="text" @bind="_customer.Name" placeholder="客户名称" /> <input type="email" @bind="_customer.Email" placeholder="邮箱" /> <button @onclick="HandleUpdate">保存修改</button> } @code { [Parameter] public int CustomerId { get; set; } private Customer _customer; protected override async Task OnInitializedAsync() { _customer = await _customerRepository.GetByIdAsync(CustomerId); } private async Task HandleUpdate() { await _customerRepository.UpdateAsync(_customer); NavigationManager.NavigateTo("/customers"); } }
关键注意事项
- 实体主键要求:所有实体必须定义主键(EF Core默认识别
Id或[实体名]Id作为主键),否则GetByIdAsync会失效。 - 特殊业务扩展:如果某张表需要自定义逻辑(如复杂查询、事务),可以继承通用仓储实现子类,比如
CustomerRepository : Repository<Customer>,添加专属方法。 - 事务控制:若需要多表操作的事务,可在业务层注入
DbContext手动开启事务,或在仓储中扩展事务方法。 - SaveChanges时机:示例中每个CRUD操作都自动调用
SaveChangesAsync,如果需要批量操作(如同时添加多个实体),可以先调用AddAsync,最后统一调用SaveChangesAsync提升性能。
内容的提问来源于stack exchange,提问作者Alamdar Khan
相关产品推荐
相关产品推荐

