当前位置:首页 >休闲 >.NET之生成数据库全流程 采用EFCore作为ORM框架

.NET之生成数据库全流程 采用EFCore作为ORM框架

2024-06-26 13:26:15 [百科] 来源:避面尹邢网

.NET之生成数据库全流程

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

[[398365]]

本文转载自微信公众号「鹏祥」,流程作者AZRNG。生成数据转载本文请联系鹏祥公众号。库全

开篇语

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

.NET之生成数据库全流程 采用EFCore作为ORM框架

本次示例环境:vs2019、库全net5、流程mysql

.NET之生成数据库全流程 采用EFCore作为ORM框架

创建项目

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

.NET之生成数据库全流程 采用EFCore作为ORM框架

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

  1. dotnet new webapi -o Net5ByDocker 

创建实体类

安装连接MySQL数据库组件

  1. <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0" /> 
  2.     <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Json.Newtonsoft" Version="5.0.0" /> 

增加实体类

  1. [Table("user")] 
  2.   public class User 
  3.   {  
  4.       public User() 
  5.       {  
  6.           Id = Guid.NewGuid().ToString(); 
  7.       } 
  8.  
  9.       public User(string account, string password, string creater) : this() 
  10.       {  
  11.           Account = account; 
  12.           Password = password; 
  13.           Deleted = false; 
  14.           SetCreater(creater); 
  15.       } 
  16.  
  17.       [Key] 
  18.       [Comment("主键")] 
  19.       [StringLength(36)] 
  20.       [Required] 
  21.       public string Id {  get; private set; } 
  22.  
  23.       [Comment("帐号")] 
  24.       [StringLength(36)] 
  25.       [Required] 
  26.       public string Account {  get; private set; } 
  27.  
  28.       [Comment("密码")] 
  29.       [StringLength(36)] 
  30.       [Required] 
  31.       public string Password {  get; private set; } 
  32.  
  33.       [Comment("余额")] 
  34.       [Column(TypeName = "decimal(18, 2)")] 
  35.       [Required] 
  36.       public decimal Money {  get; set; } 
  37.  
  38.       [Comment("是否删除")] 
  39.       [Column(TypeName = "tinyint(1)")] 
  40.       [Required] 
  41.       public bool Deleted {  get; private set; } 
  42.  
  43.       [Comment("创建人")] 
  44.       [StringLength(20)] 
  45.       [Required] 
  46.       public string Creater {  get; private set; } 
  47.  
  48.       [Comment("创建时间")] 
  49.       [Required] 
  50.       public DateTime CreateTime {  get; private set; } 
  51.  
  52.       [Comment("修改人")] 
  53.       [StringLength(20)] 
  54.       [Required] 
  55.       public string Modifyer {  get; private set; } 
  56.  
  57.       [Comment("修改时间")] 
  58.       [Required] 
  59.       public DateTime ModifyTime {  get; private set; } 
  60.  
  61.       public void SetCreater(string name) 
  62.       {  
  63.           Creater = name; 
  64.           CreateTime = DateTime.Now; 
  65.           SetModifyer(name); 
  66.       } 
  67.  
  68.       public void SetModifyer(string name) 
  69.       {  
  70.           Modifyer = name; 
  71.           ModifyTime = DateTime.Now; 
  72.       } 
  73.   } 

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

增加数据库上下文OpenDbContext

  1. public class OpenDbContext : DbContext 
  2.     {  
  3.         public OpenDbContext(DbContextOptions<OpenDbContext> options) 
  4.             : base(options) 
  5.         {  
  6.         } 
  7.  
  8.         public DbSet<User> Users {  get; set; } 
  9.     } 

Startup注入连接数据库操作

  1. var connection = Configuration["DbConfig:Mysql:ConnectionString"]; 
  2.             var migrationsAssembly = IntrospectionExtensions.GetTypeInfo(typeof(Startup)).Assembly.GetName().Name; 
  3.             services.AddDbContext<OpenDbContext>(option => option.UseMySql(connection,生成数据 ServerVersion.AutoDetect(connection), x => 
  4.             {  
  5.                 x.UseNewtonsoftJson(); 
  6.                 x.MigrationsAssembly(migrationsAssembly); 
  7.             })); 

生成迁移文件

引用组件

  1. <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5"> 
  2. <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.5"> 

迁移命令

  1. add-migration Init 

结果

image.png

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

数据种子

增加OpenDbSend类,流程添加数据种子

  1. public class OpenDbSend 
  2.  {  
  3.      /// <summary> 
  4.      /// 生成数据库以及数据种子 
  5.      /// </summary> 
  6.      /// <param name="dbContext">数据库上下文</param> 
  7.      /// <param name="loggerFactory">日志</param> 
  8.      /// <param name="retry">重试次数</param> 
  9.      /// <returns></returns> 
  10.      public static async Task SeedAsync(OpenDbContext dbContext, 
  11.          ILoggerFactory loggerFactory, 
  12.          int? retry = 0) 
  13.      {  
  14.          int retryForAvailability = retry.Value; 
  15.          try 
  16.          {  
  17.              dbContext.Database.Migrate();//如果当前数据库不存在按照当前 model 创建,如果存在则将数据库调整到和当前 model 匹配 
  18.              await InitializeAsync(dbContext).ConfigureAwait(false); 
  19.  
  20.              //if (dbContext.Database.EnsureCreated())//如果当前数据库不存在按照当前 model创建,如果存在则不管了。 
  21.              //  await InitializeAsync(dbContext).ConfigureAwait(false); 
  22.          } 
  23.          catch (Exception ex) 
  24.          {  
  25.              if (retryForAvailability < 3) 
  26.              {  
  27.                  retryForAvailability++; 
  28.                  var log = loggerFactory.CreateLogger<OpenDbSend>(); 
  29.                  log.LogError(ex.Message); 
  30.                  await SeedAsync(dbContext, loggerFactory, retryForAvailability).ConfigureAwait(false); 
  31.              } 
  32.          } 
  33.      } 
  34.  
  35.      /// <summary> 
  36.      /// 初始化数据 
  37.      /// </summary> 
  38.      /// <param name="context"></param> 
  39.      /// <returns></returns> 
  40.      public static async Task InitializeAsync(OpenDbContext context) 
  41.      {  
  42.          if (!context.Set<User>().Any()) 
  43.          {  
  44.              await context.Set<User>().AddAsync(new User("azrng", "123456", "azrng")).ConfigureAwait(false); 
  45.              await context.Set<User>().AddAsync(new User("张三", "123456", "azrng")).ConfigureAwait(false); 
  46.          } 
  47.          await context.SaveChangesAsync().ConfigureAwait(false); 
  48.      } 
  49.  } 

设置项目启动时候调用

  1. public static async Task Main(string[] args) 
  2.        {  
  3.            var host = CreateHostBuilder(args).Build(); 
  4.            using (var scope = host.Services.CreateScope()) 
  5.            {  
  6.                var services = scope.ServiceProvider; 
  7.                var loggerFactory = services.GetRequiredService<ILoggerFactory>(); 
  8.                var _logger = loggerFactory.CreateLogger<Program>(); 
  9.                try 
  10.                {  
  11.                    var openContext = services.GetRequiredService<OpenDbContext>(); 
  12.                    await OpenDbSend.SeedAsync(openContext, loggerFactory).ConfigureAwait(false); 
  13.                } 
  14.                catch (Exception ex) 
  15.                {  
  16.                    _logger.LogError(ex, $"项目启动出错  { ex.Message}"); 
  17.                } 
  18.            } 
  19.  
  20.            await host.RunAsync().ConfigureAwait(false); 
  21.        } 

生成数据库

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

image.png

表结构如下

image.png

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

查询数据

  1. /// <summary> 
  2. /// 用户接口 
  3. /// </summary> 
  4. public interface IUserService 
  5. {  
  6.     string GetName(); 
  7.  
  8.     /// <summary> 
  9.     /// 查询用户信息 
  10.     /// </summary> 
  11.     /// <param name="account"></param> 
  12.     /// <returns></returns> 
  13.     Task<User> GetDetailsAsync(string account); 
  14.  
  15. /// <summary> 
  16. /// 用户实现 
  17. /// </summary> 
  18. public class UserService : IUserService 
  19. {  
  20.     private readonly OpenDbContext _dbContext; 
  21.  
  22.     public UserService(OpenDbContext dbContext) 
  23.     {  
  24.         _dbContext = dbContext; 
  25.     } 
  26.  
  27.     public string GetName() 
  28.     {  
  29.         return "AZRNG"; 
  30.     } 
  31.  
  32.     ///<inheritdoc cref="IUserService.GetDetailsAsync(string)"/> 
  33.     public async Task<User> GetDetailsAsync(string account) 
  34.     {  
  35.         return await _dbContext.Set<User>().FirstOrDefaultAsync(t => t.Account == account).ConfigureAwait(false); 
  36.     } 

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

控制器方法

  1. /// <summary> 
  2. /// 查询用户详情 
  3. /// </summary> 
  4. /// <param name="account"></param> 
  5. /// <returns></returns> 
  6. [HttpGet] 
  7. public async Task<ActionResult<User>> GetDetailsAsync(string account) 
  8. {  
  9.     return await _userService.GetDetailsAsync(account).ConfigureAwait(false); 

查询结果

  1. {  
  2.   "id": "e8976d0a-6ee9-4e2e-b8d8-1fe6e85b727b", 
  3.   "account": "azrng", 
  4.   "password": "123456", 
  5.   "money": 0, 
  6.   "deleted": false, 
  7.   "creater": "azrng", 
  8.   "createTime": "2021-05-09T15:48:45.730302", 
  9.   "modifyer": "azrng", 
  10.   "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数据库项目

(责任编辑:百科)

    推荐文章
    热点阅读