.NET之生成数据库全流程

发布于 2021-05-13 21:37 ,所属分类:数据库和大数据技术学习资料

开篇语

本文主要是回顾下从项目创建到生成数据到数据库(代码优先)的全部过程。采用EFCore作为ORM框架。

本次示例环境:vs2019、net5、mysql

创建项目

本次事例代码是用过vs2019创建的ASP.NET Core Web API项目

可以通过可视化界面创建或者通过命令行创建

dotnetnewwebapi-oNet5ByDocker

创建实体类

安装连接MySQL数据库组件

<PackageReferenceInclude="Pomelo.EntityFrameworkCore.MySql"Version="5.0.0"/>
<PackageReferenceInclude="Pomelo.EntityFrameworkCore.MySql.Json.Newtonsoft"Version="5.0.0"/>

增加实体类

[Table("user")]
publicclassUser
{
publicUser()
{
Id=Guid.NewGuid().ToString();
}

publicUser(stringaccount,stringpassword,stringcreater):this()
{
Account=account;
Password=password;
Deleted=false;
SetCreater(creater);
}

[Key]
[Comment("主键")]
[StringLength(36)]
[Required]
publicstringId{get;privateset;}

[Comment("帐号")]
[StringLength(36)]
[Required]
publicstringAccount{get;privateset;}

[Comment("密码")]
[StringLength(36)]
[Required]
publicstringPassword{get;privateset;}

[Comment("余额")]
[Column(TypeName="decimal(18,2)")]
[Required]
publicdecimalMoney{get;set;}

[Comment("是否删除")]
[Column(TypeName="tinyint(1)")]
[Required]
publicboolDeleted{get;privateset;}

[Comment("创建人")]
[StringLength(20)]
[Required]
publicstringCreater{get;privateset;}

[Comment("创建时间")]
[Required]
publicDateTimeCreateTime{get;privateset;}

[Comment("修改人")]
[StringLength(20)]
[Required]
publicstringModifyer{get;privateset;}

[Comment("修改时间")]
[Required]
publicDateTimeModifyTime{get;privateset;}

publicvoidSetCreater(stringname)
{
Creater=name;
CreateTime=DateTime.Now;
SetModifyer(name);
}

publicvoidSetModifyer(stringname)
{
Modifyer=name;
ModifyTime=DateTime.Now;
}
}

这种只是增加实体类类型的一种方式,可能这种看着比较乱,还可以通过OnModelCreating实现,详情看参考文档

增加数据库上下文OpenDbContext

publicclassOpenDbContext:DbContext
{
publicOpenDbContext(DbContextOptions<OpenDbContext>options)
:base(options)
{
}

publicDbSet<User>Users{get;set;}
}

Startup注入连接数据库操作

varconnection=Configuration["DbConfig:Mysql:ConnectionString"];
varmigrationsAssembly=IntrospectionExtensions.GetTypeInfo(typeof(Startup)).Assembly.GetName().Name;
services.AddDbContext<OpenDbContext>(option=>option.UseMySql(connection,ServerVersion.AutoDetect(connection),x=>
{
x.UseNewtonsoftJson();
x.MigrationsAssembly(migrationsAssembly);
}));

生成迁移文件

引用组件

<PackageReferenceInclude="Microsoft.EntityFrameworkCore.Design"Version="5.0.5">
<PackageReferenceInclude="Microsoft.EntityFrameworkCore.Tools"Version="5.0.5">

迁移命令

add-migrationInit

结果

image.png

要看下生成的迁移文件是否是自己预期的那样子,也可以在这一步就生成数据库,命令:Update-Database

数据种子

增加OpenDbSend类,添加数据种子

publicclassOpenDbSend
{
///<summary>
///生成数据库以及数据种子
///</summary>
///<paramname="dbContext">数据库上下文</param>
///<paramname="loggerFactory">日志</param>
///<paramname="retry">重试次数</param>
///<returns></returns>
publicstaticasyncTaskSeedAsync(OpenDbContextdbContext,
ILoggerFactoryloggerFactory,
int?retry=0)
{
intretryForAvailability=retry.Value;
try
{
dbContext.Database.Migrate();//如果当前数据库不存在按照当前model创建,如果存在则将数据库调整到和当前model匹配
awaitInitializeAsync(dbContext).ConfigureAwait(false);

//if(dbContext.Database.EnsureCreated())//如果当前数据库不存在按照当前 model创建,如果存在则不管了。
//awaitInitializeAsync(dbContext).ConfigureAwait(false);
}
catch(Exceptionex)
{
if(retryForAvailability<3)
{
retryForAvailability++;
varlog=loggerFactory.CreateLogger<OpenDbSend>();
log.LogError(ex.Message);
awaitSeedAsync(dbContext,loggerFactory,retryForAvailability).ConfigureAwait(false);
}
}
}

///<summary>
///初始化数据
///</summary>
///<paramname="context"></param>
///<returns></returns>
publicstaticasyncTaskInitializeAsync(OpenDbContextcontext)
{
if(!context.Set<User>().Any())
{
awaitcontext.Set<User>().AddAsync(newUser("azrng","123456","azrng")).ConfigureAwait(false);
awaitcontext.Set<User>().AddAsync(newUser("张三","123456","azrng")).ConfigureAwait(false);
}
awaitcontext.SaveChangesAsync().ConfigureAwait(false);
}
}

设置项目启动时候调用

publicstaticasyncTaskMain(string[]args)
{
varhost=CreateHostBuilder(args).Build();
using(varscope=host.Services.CreateScope())
{
varservices=scope.ServiceProvider;
varloggerFactory=services.GetRequiredService<ILoggerFactory>();
var_logger=loggerFactory.CreateLogger<Program>();
try
{
varopenContext=services.GetRequiredService<OpenDbContext>();
awaitOpenDbSend.SeedAsync(openContext,loggerFactory).ConfigureAwait(false);
}
catch(Exceptionex)
{
_logger.LogError(ex,$"项目启动出错{ex.Message}");
}
}

awaithost.RunAsync().ConfigureAwait(false);
}

生成数据库

启动项目,自动生成数据库

image.png

表结构如下

image.png

如果后期数据库字段或者结构有变动,可以再次生成迁移文件然后生成数据库

查询数据

///<summary>
///用户接口
///</summary>
publicinterfaceIUserService
{
stringGetName();

///<summary>
///查询用户信息
///</summary>
///<paramname="account"></param>
///<returns></returns>
Task<User>GetDetailsAsync(stringaccount);
}

///<summary>
///用户实现
///</summary>
publicclassUserService:IUserService
{
privatereadonlyOpenDbContext_dbContext;

publicUserService(OpenDbContextdbContext)
{
_dbContext=dbContext;
}

publicstringGetName()
{
return"AZRNG";
}

///<inheritdoccref="IUserService.GetDetailsAsync(string)"/>
publicasyncTask<User>GetDetailsAsync(stringaccount)
{
returnawait_dbContext.Set<User>().FirstOrDefaultAsync(t=>t.Account==account).ConfigureAwait(false);
}
}

一般更推荐建立指定的返回Model类,然后只查询需要的内容,不直接返回实体类

控制器方法

///<summary>
///查询用户详情
///</summary>
///<paramname="account"></param>
///<returns></returns>
[HttpGet]
publicasyncTask<ActionResult<User>>GetDetailsAsync(stringaccount)
{
returnawait_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

相关资源