.NET之生成数据库全流程实现
.net之生成数据库全流程实现
开篇语
本文主要是回顾下从项目创建到生成数据到数据库(代码优先)的全部过程。采用efcore作为orm框架。
本次示例环境:vs2019、net5、mysql
创建项目
本次事例代码是用过vs2019创建的asp.net core web api项目
可以通过可视化界面创建或者通过命令行创建
dotnet new webapi -o net5bydocker
创建实体类
安装组件
<packagereference include="pomelo.entityframeworkcore.mysql" version="5.0.0" /> <packagereference include="pomelo.entityframeworkcore.mysql.json.newtonsoft" version="5.0.0" />
增加实体类
[table("user")] public class user { public user() { id = guid.newguid().tostring(); } public user(string account, string password, string creater) : this() { account = account; password = password; deleted = false; setcreater(creater); } [key] [comment("主键")] [stringlength(36)] [required] public string id { get; private set; } [comment("帐号")] [stringlength(36)] [required] public string account { get; private set; } [comment("密码")] [stringlength(36)] [required] public string password { get; private set; } [comment("余额")] [column(typename = "decimal(18, 2)")] [required] public decimal money { get; set; } [comment("是否删除")] [column(typename = "tinyint(1)")] [required] public bool deleted { get; private set; } [comment("创建人")] [stringlength(20)] [required] public string creater { get; private set; } [comment("创建时间")] [required] public datetime createtime { get; private set; } [comment("修改人")] [stringlength(20)] [required] public string modifyer { get; private set; } [comment("修改时间")] [required] public datetime modifytime { get; private set; } public void setcreater(string name) { creater = name; createtime = datetime.now; setmodifyer(name); } public void setmodifyer(string name) { modifyer = name; modifytime = datetime.now; } }
这种只是增加实体类类型的一种方式,可能这种看着比较乱,还可以通过onmodelcreating实现,详情看参考文档
增加数据库上下文opendbcontext
public class opendbcontext : dbcontext { public opendbcontext(dbcontextoptions<opendbcontext> options) : base(options) { } public dbset<user> users { get; set; } }
startup注入连接数据库操作
var connection = configuration["dbconfig:mysql:connectionstring"]; var migrationsassembly = introspectionextensions.gettypeinfo(typeof(startup)).assembly.getname().name; services.adddbcontext<opendbcontext>(option => option.usemysql(connection, serverversion.autodetect(connection), x => { x.usenewtonsoftjson(); x.migrationsassembly(migrationsassembly); }));
生成迁移文件
引用组件
<packagereference include="microsoft.entityframeworkcore.design" version="5.0.5"> <packagereference include="microsoft.entityframeworkcore.tools" version="5.0.5">
迁移命令
add-migration init
结果
要看下生成的迁移文件是否是自己预期的那样子,也可以在这一步就生成数据库,命令:update-database
数据种子
增加opendbsend类,添加数据种子
public class opendbsend { /// <summary> /// 生成数据库以及数据种子 /// </summary> /// <param name="dbcontext">数据库上下文</param> /// <param name="loggerfactory">日志</param> /// <param name="retry">重试次数</param> /// <returns></returns> public static async task seedasync(opendbcontext dbcontext, iloggerfactory loggerfactory, int? retry = 0) { int retryforavailability = retry.value; try { dbcontext.database.migrate();//如果当前数据库不存在按照当前 model 创建,如果存在则将数据库调整到和当前 model 匹配 await initializeasync(dbcontext).configureawait(false); //if (dbcontext.database.ensurecreated())//如果当前数据库不存在按照当前 model创建,如果存在则不管了。 // await initializeasync(dbcontext).configureawait(false); } catch (exception ex) { if (retryforavailability < 3) { retryforavailability++; var log = loggerfactory.createlogger<opendbsend>(); log.logerror(ex.message); await seedasync(dbcontext, loggerfactory, retryforavailability).configureawait(false); } } } /// <summary> /// 初始化数据 /// </summary> /// <param name="context"></param> /// <returns></returns> public static async task initializeasync(opendbcontext context) { if (!context.set<user>().any()) { await context.set<user>().addasync(new user("azrng", "123456", "azrng")).configureawait(false); await context.set<user>().addasync(new user("张三", "123456", "azrng")).configureawait(false); } await context.savechangesasync().configureawait(false); } }
设置项目启动时候调用
public static async task main(string[] args) { var host = createhostbuilder(args).build(); using (var scope = host.services.createscope()) { var services = scope.serviceprovider; var loggerfactory = services.getrequiredservice<iloggerfactory>(); var _logger = loggerfactory.createlogger<program>(); try { var opencontext = services.getrequiredservice<opendbcontext>(); await opendbsend.seedasync(opencontext, loggerfactory).configureawait(false); } catch (exception ex) { _logger.logerror(ex, $"项目启动出错 {ex.message}"); } } await host.runasync().configureawait(false); }
生成数据库
启动项目,自动生成数据库
表结构如下
如果后期数据库字段或者结构有变动,可以再次生成迁移文件然后生成数据库
查询数据
/// <summary> /// 用户接口 /// </summary> public interface iuserservice { string getname(); /// <summary> /// 查询用户信息 /// </summary> /// <param name="account"></param> /// <returns></returns> task<user> getdetailsasync(string account); } /// <summary> /// 用户实现 /// </summary> public class userservice : iuserservice { private readonly opendbcontext _dbcontext; public userservice(opendbcontext dbcontext) { _dbcontext = dbcontext; } public string getname() { return "azrng"; } ///<inheritdoc cref="iuserservice.getdetailsasync(string)"/> public async task<user> getdetailsasync(string account) { return await _dbcontext.set<user>().firstordefaultasync(t => t.account == account).configureawait(false); } }
一般更推荐建立指定的返回model类,然后只查询需要的内容,不直接返回实体类
控制器方法
/// <summary> /// 查询用户详情 /// </summary> /// <param name="account"></param> /// <returns></returns> [httpget] public async task<actionresult<user>> getdetailsasync(string account) { return await _userservice.getdetailsasync(account).configureawait(false); }
查询结果
{ "id": "e8976d0a-6ee9-4e2e-b8d8-1fe6e85b727b", "account": "azrng", "password": "123456", "money": 0, "deleted": false, "creater": "azrng", "createtime": "2021-05-09t15:48:45.730302", "modifyer": "azrng", "modifytime": "2021-05-09t15:48:45.730425" }
参考文档
实体类型:https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=data-annotations
实体属性:https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-properties?tabs=data-annotations%2cwithout-nrt
关于.net之生成数据库全流程实现的文章就介绍至此,更多相关.net 生成数据库内容请搜索硕编程以前的文章,希望大家多多支持硕编程!