首页 > 作文

.NET 6开发TodoList应用引入数据存储

更新时间:2023-04-04 12:25:56 阅读: 评论:0

一.需求

作为后端crud程序员(bushi,数据存储是开发后端服务一个非常重要的组件。对我们的todolist项目来说,自然也需要配置数据存储。

目前的需求很简单:

需要能持久化todolist对象并对其进行操作;需要能持久化todoitem对象并对其进行操作;

问题是,我们打算如何存储数据?

存储组件的选择非常多:以mssql rver/postgres/mysql/sqlite等为代表的关系型数据库,以mongodb/elasticarch等为代表的非关系型数据库,除此之外,我们还可以在开发阶段选择内存数据库,在云上部署的时候还可以选择类似azure cosmos db/aws dynamodb以及云上提供的多种关系型数据库。

应用程序使用数据库服务,一般都是借助成熟的第三方orm框架,而在.net后端服务开发的过程中,使用的最多的两个orm框架应该是:entityframeworkcore和dapper,相比之下,efcore的使用率更高一些。所以我们也选择efcore来进行演示。

二.目标

在这篇文章中,我们仅讨论如何实现数据存储基础设施的引入,具体的实体定义和操作后面专门来说。

使创业梦用mssql rver容器作为数据存储组件(前提是电脑上需要安装docker环境,下载并安装docker desktop即可);

这样选择的理由也很简单,对于使用mac的小伙伴来说,使用容器来启动mssql rver可以避免因为非windows平台导致的示例无法运行的问题。

三.原理和思路

因为我们对开发环境和生产环境的配置有差异,那先来看看共性的部分:

引入efcore相关的nuget包并进行配置;添加dbcontext对象并进行依赖注入;修改相关appttings.{environment}.json文件;主程序配置。本地运行mssql rver容器并实现数据持久化;

同一样,和具体的第三方对接的逻辑我们还是放到infrastructure里面去,应用程序中只保留对外部服务的抽象操作。

四.实现

1. 引入nuget包并进行配置

需要在infrastructure项目中引入以下nuget包:

microsoft.entityframeworkcore.sqlrver# 第二个包是用于使用powershell命令(add-migration/update-databa/...)需要的,如果使用eftool,可以不安装这个包。microsoft.entityframeworkcore.tools

为了使用eftool,需要在api项目中引入以下nuget包:

microsoft.entityframeworkcore.design

2. 添加dbcontext对象并进行配置#

在这一步里,我们要添加的是一个具体的dbcontext对象,这对于有经验的开发者来说并不是很难的任务。但是在具体实现之前,我们可以花一点时间考虑一下现在的clean architecture结构:我们的目的是希望除了infrastructure知道具体交互的第三方是什么,在application以及domain里都要屏蔽底层的具体实现。换言之就是需要在infrastrcuture之外的项目中使用接口来做具体实现的抽象,那么我们在application中新建一个common/interfaces文件夹用于存放应用程序定义的抽象接口iapplicationdbcontext:

namespace todolist.application.common.interfaces;public interface iapplicationdbcontext{    task<int> savechangesasync(cancellationtoken cancellationtoken);}

接下来在infrastructure项目中新建persistence文件夹用来存放和数据持久化相关的具体逻辑,我们在其中定义dbcontext对象并实现刚才定义的接口。

using microsoft.entityframeworkcore;using todolist.applic氧化分解ation.common.interfaces;namespace todolist.infrastructure.persistence;public class todolistdbcontext : dbcontext, iapplicationdbcontext{    public todolistdbcontext(dbcontextoptions<todolistdbcontext> options) : ba(options)    {    }}

这里的处理方式可能会引起困惑,这个iapplicationdbcontext存在的意义是什么。这里的疑问和关于要不要使用repository模式有关,国外多位大佬讨论过这个问题,即repository是不是必须的。可以简单理解大家达成的共识是:不是必须的,如果不是有某些特别的数据库访问逻辑,或者有足够的理由需要使用repository模式,那就保持架构上的简洁,在application层的多个cqrs handlers鲁人徒越中直接注入该iapplicationdbcontext去访问数据库并进行操作。如果需要使用repository模式,那在这里就没有必要定义这个接口来使用了,application中只需要定义irepository<t>,在infrastructure中实现的barepository中访问dbcontext即可。

我们后面是需要使用repository的,是因为希望演示最常用的开发模式,但是在这一篇中我保留iapplicationdbconetxt的原因是也希望展示一种不同的实现风格,后面我们还是会专注到repository上的。

需要的对象添加好了,下一步是配置dbcontext,我们还是遵循当前的架构风格,在infrastructure项目中添加dependencyinjection.cs文件用于添加所有第三方的依赖:

using microsoft.entityframeworkcore;using microsoft.extensions.configuration;using microsoft.extensions.dependencyinjection;using todolist.application.common.interfaces;using todolist.infrastructure.persistence;namespace todolist.infrastructure;public static class dependencyinjection{    public static irvicecollection addinfrastructure(this irvicecollection rvices, iconfiguration configuration)    {        rvices.adddbcontext<todolistdbcontext>(options =>            options.usqlrver(                configuration.getconnectionstring("sqlrverconnection"),                b => b.migrationsasmbly(typeof(todolistdbcontext).asmbly.fullname)));        rvices.addscoped<iapplicationdbcontext>(provider => provider.getrequiredrvice<todolistdbcontext>());        return rvices;    }}

3. 配置文件修改

我们对appttings.development.json文件进行配置:

{  "logging": {    "loglevel": {      "default": "information",      "microsoft.aspnetcore": "warning"    }  },  "ufiletolog": true,  "connectionstrings": {    "sqlrverconnection": "rver=localhost,1433;databa=todolistdb;ur id=sa;password=strongpwd123;"  }}

这里需要说明的是如果是使用mssql rver默认端口1433的话,连接字符串里是可以不写的,但是为了展示如果使用的不是默认端口应该如何配置,还是显式写在这里了供大家参考。

4. 主程序配置

在api项目中,我们只需要调用上面写好的扩展方法,就可以完成配置。

var builder = webapplication.createbuilder(args);// add rvices to the container.builder.configurelog();builder.rvices.addcontrollers();builder.rvices.addendpointsapiexplorer();builder.rvices.addswaggergen();// 添加基础设施配置builder.rvices.addinfrastructure(builder.configuration);// 省略以下...

5. 本地运行mssql rver容器及数据持久化

在保证本地docker环境正常启动之后,运行以下命令:

# 拉取mssql镜像$ docker pull mcr.microsoft.com/mssql/rver:2019-latest2019-latest: pulling from mssql/rver7b1a6ab2e44d: already exists 4ffe416cf537: pull complete fff1d174f64f: pull complete 3588fd79aff7: pull complete c8203457909f: pull complete digest: sha256:a098c9ff6fbb8e1c9608ad7511fa42dba8d22e0d50b48302761717840ccc26afstatus: downloaded newer image for mcr.microsoft.com/mssql/rver:2019-latestmcr.microsoft.com/mssql/rver:2019-latest# 创建持久化存储$ docker create -v /var/opt/mssql --name mssqldata  mcr.microsoft.com/mssql/rver:2019-latest /bin/true3c144419db7fba26398aa45f77891b00a3253c23e9a1d03e193a3cf523c66ce1# 运行mssql容器,挂载持久化存储卷$ docker run -d --volumes-from mssqldata --name mssql -e 'accept_eula=y' -e 'sa_password=strongpwd123' -p 1433:1433 mcr.microsoft.com/mssql/rver:2019-latestd99d774f70229f688d71fd13e90165f15abc492aacec48de287d348e047a055e# 确认容器运行状态$ docker pscontainer id   image                                        command                  created          status          ports                    namesd99d774f7022   mcr.microsoft.com/mssql/rver:2019-latest   "/opt/mssql/bin/perm…"   24 conds ago   up 22 conds   0.0.0.0:1433->1433/tcp   mssql

五.验证

为了验证我们是否可以顺利连接到数据库,我们采用添加migration并在程序启动时自动进行数据库的migration方式进行:

首先安装工具:

dotnet tool install --global dotnet-ef# dotnet tool update --global dotnet-ef# 生成migration$ dotnet ef migrations add tupdb -p src/todolist.infrastructure/todolist.infrastructure.csproj -s src/todolist.api/todolist.api.csprojbuild started...build succeeded.[17:29:15 inf] entity framework core 6.0.1 initialized 'todolistdbcontext' using provider 'microsoft.entityframeworkcore.sqlrver:6.0.1' with options: migrationsasmbly=todolist.infrastructure, version=1.0.0.0, culture=neutral, publickeytoken=null done. to undo this action, u 'ef migrations remove'

为了在程序启动时进行自动migration,我们向infrastructure项目中增加一个文件applicationstartupextensions.cs并实现扩展方法:

using microsoft.aspnetcore.builder;using microsoft.entityframeworkcore;using microsoft.extensions.dependencyinjection;using todolist.infrastructure.persistence;namespace todolist.infrastructure;public static class applicationstartupextensions{    public static void migratedataba(this webapplication app)    {        using var scope = app.rvices.createscope();        var rvices = scope.rviceprovider;        try        {            var context = rvices.getrequiredrvice<todolistdbcontext>();            context.databa.migrate();        }        catch (exception ex)        {            throw new exception($"an error occurred migrating the db: {ex.message}");        }    }}

并在api项目的program.cs中调用扩展方法:

// 省略以上...app.mapcontrollers();// 调用扩展方法app.migratedataba();app.run();

最后运行主程序:

$ dotnet run --project src/todolist.apibuilding...[17:32:32 inf] entity framework core 6.0.1 initialized 'todolistdbcontext' using provider 'microsoft.entityframeworkcore.sqlrver:6.0.1' with options: migrationsasmbly=t摆布odolist.infrastructure, version=1.0.0.0, culture=neutral, publickeytoken=null [17:32:32 inf] executed dbcommand (22ms) [parameters=[], commandtype='text', commandtimeout='30']lect 1[17:32:32 inf] executed dbcommand (19ms) [parameters=[], commandtype='text', commandtimeout='30']lect object_id(n'[__efmigrationshistory]');[17:32:32 inf] executed dbcommand (3ms) [parameters=[], commandtype='text', commandtimeout='30']lect 1[17:32:32 inf] executed dbcommand (2ms) [parameters=[], commandtype='text', commandtimeout='30']lect object_id(n'[__efmigrationshistory]');[17:32欧洲文化:33 inf] executed dbcommand (4ms) [parameters=[], commandtype='text', commandtimeout='30']lect [migrationid], [productversion]from [__efmigrationshistory]order by [migrationid];[17:32:33 inf] applying migration '20211220092915_tupdb'.[17:32:33 inf] executed dbcommand (4ms) [parameters=[], commandtype='text', commandtimeout='30']inrt into [__efmigrationshistory] ([migrationid], [productversion])values (n'20211220092915_tupdb', n'6.0.1');[17:32:33 inf] now listening on: https://localhost:7039[17:32:33 inf] now listening on: http://localhost:5050[17:32:33 inf] application started. press ctrl+c to shut down.[17:32:33 inf] hosting environment: development[17:32:33 inf] content root path: /urs/yu.li1/projects/asinta/blogs/cnblogs/todolist/src/todolist.api/

使用数据库工具连接容器数据库,可以看到migration已经成功地写入数据库表__efmigrationshistory了:

本篇文章仅完成了数据存储服务的配置工作,目前还没有添加任何实体对象和数据库表定义,所以暂时没有可视化的验证,仅我们可以运行程序看我们的配置是否成功:

总结:

在本文中,我们探讨并实现了如何给.net 6 web api项目添加数据存储服务并进行配置,下一篇开始将会深入数据存储部分,定义实体,构建repository模式和eddata等操作。

到此这篇关于.net 6开发todolist应用引入数据存储的文章就介绍到这了,更多相关.net 6开发todolist应用内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 12:25:54,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/4683efe49b77c1a7b1de1589852b55ab.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:.NET 6开发TodoList应用引入数据存储.doc

本文 PDF 下载地址:.NET 6开发TodoList应用引入数据存储.pdf

标签:数据库   项目   数据存储   容器
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图