.NET之生成數(shù)據(jù)庫全流程實(shí)現(xiàn)
開篇語
本文主要是回顧下從項(xiàng)目創(chuàng)建到生成數(shù)據(jù)到數(shù)據(jù)庫(代碼優(yōu)先)的全部過程。采用EFCore作為ORM框架。
本次示例環(huán)境:vs2019、net5、mysql
創(chuàng)建項(xiàng)目
本次事例代碼是用過vs2019創(chuàng)建的ASP.NET Core Web API項(xiàng)目
可以通過可視化界面創(chuàng)建或者通過命令行創(chuàng)建
dotnet new webapi -o Net5ByDocker
創(chuàng)建實(shí)體類
安裝組件
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Json.Newtonsoft" Version="5.0.0" />
增加實(shí)體類
[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("創(chuàng)建人")]
[StringLength(20)]
[Required]
public string Creater { get; private set; }
[Comment("創(chuàng)建時間")]
[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;
}
}
這種只是增加實(shí)體類類型的一種方式,可能這種看著比較亂,還可以通過OnModelCreating實(shí)現(xiàn),詳情看參考文檔
增加數(shù)據(jù)庫上下文OpenDbContext
public class OpenDbContext : DbContext
{
public OpenDbContext(DbContextOptions<OpenDbContext> options)
: base(options)
{
}
public DbSet<User> Users { get; set; }
}
Startup注入連接數(shù)據(jù)庫操作
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
結(jié)果

要看下生成的遷移文件是否是自己預(yù)期的那樣子,也可以在這一步就生成數(shù)據(jù)庫,命令:Update-Database
數(shù)據(jù)種子
增加OpenDbSend類,添加數(shù)據(jù)種子
public class OpenDbSend
{
/// <summary>
/// 生成數(shù)據(jù)庫以及數(shù)據(jù)種子
/// </summary>
/// <param name="dbContext">數(shù)據(jù)庫上下文</param>
/// <param name="loggerFactory">日志</param>
/// <param name="retry">重試次數(shù)</param>
/// <returns></returns>
public static async Task SeedAsync(OpenDbContext dbContext,
ILoggerFactory loggerFactory,
int? retry = 0)
{
int retryForAvailability = retry.Value;
try
{
dbContext.Database.Migrate();//如果當(dāng)前數(shù)據(jù)庫不存在按照當(dāng)前 model 創(chuàng)建,如果存在則將數(shù)據(jù)庫調(diào)整到和當(dāng)前 model 匹配
await InitializeAsync(dbContext).ConfigureAwait(false);
//if (dbContext.Database.EnsureCreated())//如果當(dāng)前數(shù)據(jù)庫不存在按照當(dāng)前 model創(chuàng)建,如果存在則不管了。
// 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>
/// 初始化數(shù)據(jù)
/// </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);
}
}
設(shè)置項(xiàng)目啟動時候調(diào)用
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, $"項(xiàng)目啟動出錯 {ex.Message}");
}
}
await host.RunAsync().ConfigureAwait(false);
}
生成數(shù)據(jù)庫
啟動項(xiàng)目,自動生成數(shù)據(jù)庫

表結(jié)構(gòu)如下

如果后期數(shù)據(jù)庫字段或者結(jié)構(gòu)有變動,可以再次生成遷移文件然后生成數(shù)據(jù)庫
查詢數(shù)據(jù)
/// <summary>
/// 用戶接口
/// </summary>
public interface IUserService
{
string GetName();
/// <summary>
/// 查詢用戶信息
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
Task<User> GetDetailsAsync(string account);
}
/// <summary>
/// 用戶實(shí)現(xiàn)
/// </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類,然后只查詢需要的內(nèi)容,不直接返回實(shí)體類
控制器方法
/// <summary>
/// 查詢用戶詳情
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult<User>> GetDetailsAsync(string account)
{
return await _userService.GetDetailsAsync(account).ConfigureAwait(false);
}
查詢結(jié)果
{
"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"
}
參考文檔
實(shí)體類型:https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=data-annotations
到此這篇關(guān)于.NET之生成數(shù)據(jù)庫全流程實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān).NET 生成數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net中Null在從數(shù)據(jù)庫讀取的時候的一點(diǎn)點(diǎn)小技巧
我們先看下面的一段代碼,這段代碼其實(shí)很平常,也是我們平時做項(xiàng)目很常用的一段2012-04-04
asp.net 網(wǎng)頁動態(tài)查詢條件的實(shí)現(xiàn)
最近有一個需求,會在 mongodb 中插入各種類型的數(shù)據(jù),算是記錄業(yè)務(wù)日志的數(shù)據(jù)庫吧。因?yàn)闃I(yè)務(wù)對象類型都不同,所以插入的數(shù)據(jù)格式也完全不同2012-10-10
ASP.NET Core應(yīng)用中與第三方IoC/DI框架的整合
ASP.NET Core應(yīng)用中,針對第三方DI框架的整合可以通過在定義Startup類型的ConfigureServices方法返回一個ServiceProvider來實(shí)現(xiàn)。但是并不是那么容易的,下面通過實(shí)例給大家分享一下2017-04-04
利用noesis.Javascript開源組件.Net中執(zhí)行javascript腳本
利用Noesis.Javascript開源組件可以做到在.net中執(zhí)行js腳本,同時js腳本也能調(diào)用C#函數(shù)。這個組件的獲得方式:在NuGet中輸入搜索"Noesis"就能找到,我們來做個搜索功能:用戶能夠在textbox中輸入js腳本來篩選list記錄2013-12-12
WPF實(shí)現(xiàn)雷達(dá)掃描圖的繪制詳解
這篇文章主要介紹了如何利用WPF實(shí)現(xiàn)雷達(dá)掃描圖的繪制,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下2022-05-05
Linq中ToList()和CopyToDataTable()用法詳解
這篇文章介紹了Linq中ToList()和CopyToDataTable()的用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03

