.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
结果
要看下生成的迁移文件是否是自己预期的那样子,也可以在这一步就生成数据库,命令: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);
}
生成数据库
启动项目,自动生成数据库
表结构如下
如果后期数据库字段或者结构有变动,可以再次生成迁移文件然后生成数据库
查询数据
///<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
相关资源