开篇语

本文主要是回顾下从项目创建到生成数据到数据库(代码优先)的全部过程。采用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-properties?tabs=data-annotations%2cwithout-nrt

到此这篇关于.net之生成数据库全流程实现的文章就介绍到这了,更多相关.net 生成数据库内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!