造轮子之种子数据
1.Asp.Net Core造轮之旅:逐步构建自己的开发框架-目录2.asp.net core之Startup3.asp.net core之依赖注入4.asp.net core之中间件5.asp.net core之Host6.asp.net core之Kestrel7.asp.net core之配置8.asp.net core之Options9.asp.net core之日志10.asp.net core之路由11.asp.net core之异常处理12.asp.net core之HttpClient13.asp.net core之实时应用14.asp.net core之EfCore15.造轮子之自动依赖注入16.造轮子之日志17.造轮子之统一业务异常处理18.造轮子之统一请求响应格式19.造轮子之缓存20.造轮子之ORM集成21.造轮子之asp.net core identity22.造轮子之自定义授权策略23.造轮子之权限管理24.造轮子之多语言管理25.造轮子之角色管理26.造轮子之用户管理27.造轮子之菜单管理28.造轮子之属性注入配合懒加载构建服务抽象基类29.造轮子之EventBus30.造轮子之消息实时推送
31.造轮子之种子数据
32.造轮子之集成GraphQL33.造轮子之设置管理34.造轮子之文件管理35.造轮子之单层应用总结篇36.单层应用升级到多层应用137.单层应用升级到多层应用238.单层应用升级到多层应用3在前面我们基本把应用框架的基础设施搭建完成。接下来我们就得着手处理一下种子数据的问题。
在一个基础框架里面,种子数据很重要,比如一些基础数据,初始用户等等,这些都需要初始化,否则程序启动却无法使用就很尴尬了。
IDataSeeder#
首先定义一个种子数据接口
using Wheel.DependencyInjection;
namespace Wheel.DataSeeders
{
public interface IDataSeeder : ITransientDependency
{
Task Seed(CancellationToken cancellationToken = default);
}
}
接下来所有的种子数据实现都需要继承这个接口。
DataSeederExtensions#
封装一个扩展方法,获取所有IDataSeeder的实现,并执行数据初始化。
namespace Wheel.DataSeeders
{
public static class DataSeederExtensions
{
public static async Task<IApplicationBuilder> SeedData(this IApplicationBuilder app)
{
var dataSeeders = app.ApplicationServices.GetServices<IDataSeeder>();
foreach (var dataSeeder in dataSeeders)
{
await dataSeeder.Seed();
}
return app;
}
}
}
在Program中添加代码
var app = builder.Build();
//初始化种子信息
await app.SeedData();
这样就初步完成了种子数据的配置。
实现种子数据#
用户角色种子数据#
IdentityDataSeeder
using Microsoft.AspNetCore.Identity;
using Wheel.Domain;
using Wheel.Domain.Identity;
namespace Wheel.DataSeeders.Identity
{
public class IdentityDataSeeder : IDataSeeder
{
private readonly IBasicRepository<Role, string> _roleRepository;
private readonly IBasicRepository<User, string> _userRepository;
private readonly UserManager<User> _userManager;
private readonly IUserStore<User> _userStore;
private readonly RoleManager<Role> _roleManager;
public IdentityDataSeeder(IBasicRepository<Role, string> roleRepository, IBasicRepository<User, string> userRepository, UserManager<User> userManager, IUserStore<User> userStore, RoleManager<Role> roleManager)
{
_roleRepository = roleRepository;
_userRepository = userRepository;
_userManager = userManager;
_userStore = userStore;
_roleManager = roleManager;
}
public async Task Seed(CancellationToken cancellationToken = default)
{
if (!await _roleRepository.AnyAsync(a => a.Name == "admin"))
{
await _roleManager.CreateAsync(new Role("admin", Enums.RoleType.Admin));
}
if (!await _roleRepository.AnyAsync(a => a.Name == "user"))
{
await _roleManager.CreateAsync(new Role("user", Enums.RoleType.App));
}
if (!await _userRepository.AnyAsync(a => a.UserName == "admin"))
{
var adminUser = new User();
await _userStore.SetUserNameAsync(adminUser, "admin", cancellationToken);
var emailStore = (IUserEmailStore<User>)_userStore;
await emailStore.SetEmailAsync(adminUser, "136590076@qq.com", cancellationToken);
await _userManager.CreateAsync(adminUser, "Wheel@2023");
await _userManager.AddToRoleAsync(adminUser, "admin");
await _userManager.UpdateAsync(adminUser);
}
}
}
}
这里初始化一个普通User角色和管理后台admin角色,以及一个admin角色的账号。
多语言种子数据#
LocalizationDataSeeder
using Wheel.Domain;
using Wheel.Domain.Localization;
namespace Wheel.DataSeeders.Localization
{
public class LocalizationDataSeeder : IDataSeeder
{
private readonly IBasicRepository<LocalizationCulture, int> _localizationCultureRepository;
public LocalizationDataSeeder(IBasicRepository<LocalizationCulture, int> localizationCultureRepository)
{
_localizationCultureRepository = localizationCultureRepository;
}
public async Task Seed(CancellationToken cancellationToken = default)
{
if (!(await _localizationCultureRepository.AnyAsync(cancellationToken)))
{
await _localizationCultureRepository.InsertAsync(new LocalizationCulture() { Name = "en" }, true);
await _localizationCultureRepository.InsertAsync(new LocalizationCulture() { Name = "zh-CN"}, true);
}
}
}
}
菜单种子#
MenuDataSeeder
using Wheel.Domain;
using Wheel.Domain.Menus;
namespace Wheel.DataSeeders.Identity
{
public class MenuDataSeeder : IDataSeeder
{
private readonly IBasicRepository<Menu, Guid> _menuRepository;
public MenuDataSeeder(IBasicRepository<Menu, Guid> menuRepository)
{
_menuRepository = menuRepository;
}
public async Task Seed(CancellationToken cancellationToken = default)
{
if (!(await _menuRepository.AnyAsync(cancellationToken)))
{
await _menuRepository.InsertAsync(new Menu
{
Name = "SystemManage",
DisplayName = "系统管理",
Sort = 99,
Id = Guid.NewGuid(),
Icon = "SettingOutlined",
Path = "/System",
MenuType = Enums.MenuType.Menu,
Children = new List<Menu>
{
new Menu
{
Name = "UserManage",
DisplayName = "用户管理",
Sort = 0,
Id = Guid.NewGuid(),
Path = "/System/User",
MenuType = Enums.MenuType.Page
},
new Menu
{
Name = "RoleManage",
DisplayName = "角色管理",
Sort = 1,
Id = Guid.NewGuid(),
Path = "/System/Role",
MenuType = Enums.MenuType.Page,
},
new Menu
{
Name = "PermissionManage",
DisplayName = "权限管理",
Sort = 2,
Id = Guid.NewGuid(),
Path = "/System/Permission",
MenuType = Enums.MenuType.Page
},
new Menu
{
Name = "MenuManage",
DisplayName = "菜单管理",
Sort = 3,
Id = Guid.NewGuid(),
Path = "/System/Menu",
MenuType = Enums.MenuType.Page
},
new Menu
{
Name = "LocalizationManage",
DisplayName = "多语言管理",
Sort = 4,
Id = Guid.NewGuid(),
Path = "/System/Localization",
MenuType = Enums.MenuType.Page
},
}
}, true, cancellationToken: cancellationToken);
}
}
}
}
这里菜单初始化基础管理后台页面所需的菜单。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?