.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 生成数据库内容请搜索硕编程以前的文章,希望大家多多支持硕编程

下一节:.net集成敏感词组件的步骤

asp.net编程技术

相关文章