国产化之路-统信UOS /Nginx /Asp.Net Core+ EF Core 3.1/达梦DM8实现简单增删改查操作

引言

经过前期的准备工作,.net core 3.1的运行环境和WEB服务器已经搭建完毕,这里需要注意一下,达梦DM8数据库对于Entity Framework Core 3.1 的驱动在NuGet官方源上并没有正式发布,需要从Win64安装版本中的drivers/dotNet提取,这里需要事先准备。

创建项目

出于开发的习惯和便利性,项目的开发和调试都还是在windows的环境下面进行,打开Visual Studio 2019,创建新项目,使用ASP.NET Core web应用程序模板,项目名称自己取一下,我这里取名DmExample,版本选择ASP.NET Core 3.1为HTTPS 配置勾选去掉,暂时不需要HTTPS

点击”创建“按钮后,稍微等待一会儿,默认的MVC项目搭建完成。在Controllers目录下只有一个HomeController.cs文件,点击运行看一下:

已经可以正常跑起来,接下来我们要在这个基础下开始添加模型、连接达梦数据库、创建数据库、添加简单的增删改查的操作。

添加驱动

在添加应用之前,为了能够连接数据库和创建表,我们首先要使用NuGet包管理工具,安装如下支持包:

Microsoft.EntityFrameworkCore

Microsoft.EntityFrameworkCore.Tools

Microsoft.EntityFrameworkCore.Design

安装完以上包后,我们需要安装EF Core的达梦数据库驱动,前面提到过在官方的NuGet源中并没有达梦的EF Core驱动,但在达梦的安装盘上有提供,所以需要对NuGet包管理器的程序包源进行添加设置,将达梦数据库安装源中的EFCore.Dm3.1DmProvider作为包源引入,然后再安装。

在NuGet包管理器中,点击右上角(红框框起来的齿轮图标),弹出选项窗口:

点击窗口右上角的加号图标,然后名称输入EFCore.Dm3.1,源路径选择你光盘镜像下面的source\drivers\dotNet\EFCore.Dm3.1。以同样的方式将DmProvider包源引入,源路径:source\drivers\dotNet\DmProvider,包源设置完成后就可以安装。

如上图所示,选择程序包源EFCore.Dm3.1后,在浏览面板中会列出达梦的EntityFramework Core的驱动包,选择它然后点击”安装“。

同样,选择程序包源DmProvider后,在浏览面板中会列出达梦的DmProvider的驱动包,选择它然后点击”安装“。这里有个地方需要注意,在NuGet包源上可以搜索到DmProvider 2.0版本的包,虽然版本高于我们当前的本地版本,但这个是.NetFramework版本的,于2017年9月7日发布,不适用于Core版本的,请不要安装或更新。

添加模型

驱动安装完成后,我们要添加一个数据模型,在Models目录下添加一个User.cs用户模型,具体代码如下:

using System;
using System.ComponentModel.DataAnnotations;namespace DmExample.Models
{/// <summary>/// 用户模型/// </summary>public class User{public User(){Id = Guid.NewGuid().ToString("N");CreateTime = DateTime.Now;}[Key]public string Id { get; set; }/// <summary>/// 姓名/// </summary>public string Name { get; set; }/// <summary>/// 年龄/// </summary>public int? Age { get; set; }/// <summary>/// 性别/// </summary>public bool? Gender { get; set; }/// <summary>/// 创建日期/// </summary>public DateTime? CreateTime { get; set; }}
}

属性不多,就ID、姓名、年龄、性别、创建日期,分别使用了字符串、整型、布尔型和日期类型,对一些常规性的属性做一下数据表属性对应测试。

创建数据库

添加数据库上下文

在项目中添加DbContext目录,在目录中添加一个名为DmContext.cs的类作为达梦数据库上下文,具体代码如下:

using DmExample.Models;
using Microsoft.EntityFrameworkCore;namespace DmExample.DbContext
{/// <summary>/// 达梦数据库上下文/// </summary>public class DmContext : Microsoft.EntityFrameworkCore.DbContext{/// <summary>/// 用户/// </summary>public DbSet<User> Users { get; set; }public DmContext(DbContextOptions<DmContext> options) : base(options){}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.Entity<User>().ToTable("sys_user");}}
}

如上代码所示,DmContext继承自Microsoft.EntityFrameworkCore.DbContext,添加了用户UserDbSet,重载OnModelCreating方法,将User模型与数据库的sys_user表建立映射关系,当然也可以不指定映射关系,在不指定的情况下,默认映射成Users数据表。目前我们还没创建数据库,数据库里也还没有这个数据表,接下来需要配置数据库连接。

配置数据库连接

(1)添加数据库连接字符串

打开项目中的appsettings.json配置文件,添加数据库连接字符串,如下所示:

{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","ConnectionStrings": {"DmExample": "Server=localhost;Database=DmExampleDB;User=SYSDBA;Password=111111;"}
}

我们在appsettings.json配置文件中添加了一个ConnectionStrings的配置项,用来设置数据库连接字符串,连接字符串命名为DmExample,字符串的格式同我们连接SqlServer类似,Server为数据库地址、Database为数据库名称、UserPassword分别为连接数据库账号和密码,需要注意的一点是设置数据库地址的时候如果是本地地址,咱们往往习惯性地用Server=.来表示,但是达梦数据库不认识这种表示,会无法连接数据库,需要把点替换成localhost127.0.0.1才行,这个注意一下。

(2)注册数据库上下文

完成数据库连接字符串的添加后,我们需要在Starup.cs类中对当前的数据库上下文进行注册,微软已经为我们提供上下文注册的中间件,只要调用它就可以了,具体代码如下:

public void ConfigureServices(IServiceCollection services)
{services.AddControllersWithViews();// 注册DbContextservices.AddDbContext<DmContext>(options =>options.UseDm(Configuration.GetConnectionString("DmExample")));
}

如上代码所示,DmContext是咱们创建的达梦数据库上下文,DmExample是我们在appsettings.json配置文件中添加的数据库连接字符串,通过Configuration.GetConnectionString方法获取该数据库连接字符串。这里注意这个代码:options.UseDm,我们连接SqlServer数据库的时候是使用options.UseSqlServer,如果我们以后连接MySql数据库时是使用options.UseMySQL,使用不同的数据库需要对应的数据库驱动,UseDm就是由达梦数据库驱动提供的方法,至此数据库的连接我们已配置完成,接下来我们要创建数据库。

创建数据库

数据库连接配置完成后,我们直接使用Visual Studio 2019的程序包管理器控制台,通过命令方式来创建数据库,首先输入如下命令(initDB是我们取的名字,没有强制规定):

add-migration 'initDB'

The add-migration command is one of the key commands in code first migrations. When you make changes to your domain model and need them dded into your database you create a new migration. This is done with the Add-Migration command. In it’s simplest form you need only toprovide a migration name.

add-migration命令是code first migration中的关键命令之一。当您对领域域模型进行更改并需要将它们时添加到数据库中,您将创建一个新的迁移。这是通过Add-Migration命令完成的。用最简单的形式,你只需要提供迁移名称。

命令执行成功后会在当前的项目中创建Migrations目录, 在这个目录中我们发现有两个文件,其中一个文件由当前创建日期加上我们之前add 后面创建名字的一个记录20201002080053_initDB记录了此次更新的部分,由于我们是第一次初始化,所以里面记录了全部表结构内容,下次我们再次使用该命令做更新时,会再次添加新的记录文件,只记录更新部分;另一个名为 DmContextModelSnapshot的文件是 Migrations生成的IModel状态的快照的基类,里面记录了要生成db的内容。

接下来执行更新数据库命令:

update-database

出现如上图所示表示执行成功,为验证是否创建数据表,我们打开达梦的数据库管理工具,查看数据库是否已存在:

我们在模式->SYSDBA->表下面发现了sys_user这张表,在表空间->MAIN->表也能够看到这张表。数据表应该是创建成功了,但是就是没有发现我们在数据库连接字符串中指定的数据库名DmExampleDB,估计是达梦的数据库结构和SqlServer有所区别,这个放在后面系统性地再去学习了,至此我们数据库创建完毕,接下来开始添加针对用户的CURD操作了。

添加增删改查操作

我们选中项目中的Controllers目录,点击右键弹出下拉菜单依次点击添加->控制器,弹出添加已搭建基架的新项窗口,选择”视图使用Entity Framework的MVC控制器“,然后点击”确定“按钮,如下图所示:

点击”确定“按钮后弹出添加视图的配置窗口,模型类选择User,数据上下文类选择DmContext,控制器名称默认UsersController,然后点击"添加"按钮。

稍微等待片刻后,我们看到在Controllers目录中已经生成了UsersController类,打开这个类文件,增删改查的代码都已经生成;点开Views视图目录,下面新增了Users目录,在该目录里边增删改查的视图也已全部生成。

用户操作的功能基本都有了,我们稍作改造就可以使用了。首先,我们要在首页上添加用户的User的入口菜单,以便对用户进行操作,打开Views/Shared/_Layout.cshtml,添加如下图代码:

另外,我们在User模型类中添加了构造函数,对新建的User对象的Id和CreateTime,设置了默认值,所以我们在创建的时候就不必要再输这两个值了,编辑Views/Users/Create.cshtml,去掉这两个属性的代码:

编辑Views/Users/Edit.cshtml,将编辑CreateTime的输入框修改为隐藏类型,编辑的时候不需要输入了:

最后,我们再修改一下Views/Users/Index.cshtml,在列表页里添加ID列,把它显示出来:

至此我们代码修改完毕。

测试运行

完成以上的创建和修改,我们直接在本机上先测试运行一下,页面效果如下:

首页上多了一个User菜单,我们点击这个菜单项后,显示如下页面:

这个是用户列表页面,因为我们还未添加任何用户,所以当前列表是空的。我们点击"Create New"链接,跳转至添加用户的页面,来添加一个新用户试试:

注意:性别是布尔类型的,我们输入truefalse来表示,点击Create按钮添加用户,成功后自动跳转到用户列表页面,如下图所示:

添加完成后,列表页面上显示出了一条记录,为了印证记录已经插入到sys_user表里,我们打开达梦的数据库管理工具进行查看:

接下来,我们再测试一下编辑、详细、删除操作,也都没有问题,这里不再贴图,到此我们完成了简单的测试,下一步将项目先发布到本地,然后部署到Web服务器上。

注意,我们发布的时候需要修改一下数据库的连接字符串,连接地址要修改为服务器上的数据库,然后在程序包管理器控制台上再次运行update-database命令,主要目的是在服务器上创建数据库,当然如果已经创建了就不用去执行这个命令了。然后,依次点击生成->发布DmExample,弹出发布配置窗口,发布目标选择”文件夹“:

文件夹位置默认即可,然后点击”完成“按钮

摘要处默认即可,点击"发布"按钮,完成发布操作,系统会将编译的发布版本复制到指定的目标位置。

项目部署

项目的部署请参考《国产化之路-安装WEB服务器》章节中的”发布站点“,这里不再详细介绍,这里补充一项,在发布站点的时候我们需要配置反向代理,ASP.NET Core默认发布的端口号是5000,所以在配置节中我们设置的端口号对应的也是5000,但当我们的Web服务器发布多个站点时,不能使用同一个端口,那么我们如何去修改ASP.NET Core默认发布的端口号呢?经查阅资料,我们只需要在appsettings.json的配置文件里添加urls配置属性即可,具体如下:

{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","ConnectionStrings": {"DmExample": "Server=localhost;Database=DmExampleDB;User=SYSDBA;Password=dx2263111;"},"urls": "http://localhost:5005"
}

我们这里设定的默认端口为5005,然后在Web服务器里对该站点的反向代理中的端口号做相应的调整:

# DmExample
location / {proxy_pass         http://localhost:5005;proxy_http_version 1.1;proxy_set_header   Upgrade $http_upgrade;proxy_set_header   Connection keep-alive;proxy_set_header   Host $host;proxy_cache_bypass $http_upgrade;proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header   X-Forwarded-Proto $scheme;
}

一切准备就绪,在Web服务器上发布完成后,打开站点显示正常,但是当我们插入一条用户数据后报错了。

纠错

同一个站点,在我们的开发机上测试都没有问题,然后发布到统信的操作系统下就出问题,接着又试了一下将数据库连到Web服务器,运行环境还是在开发机上试了一下也没有问题,应该来讲大概率就是环境问题了,那环境问题导致哪里出问题了呢?上面的错误信息,并没有告诉我们问题出在哪里,大概意思是讲让我们切换成开发模式可以查看到更详细的错误信息,那么我们切换成开发模式看看,暂停这个站点的守护进程,使用终端进入站点目录执行下面命令:

# 切换成"Development"模式
export ASPNETCORE_ENVIRONMENT=development 
# 运行站点
dotnet DmExample.dll

然后使用浏览器打开该站点,执行用户插入操作,页面显示信息变成如下显示:

反馈的应该是插入的某个字段数据类型不对,原本输入的是数字的位置输入了非数字的字符,导致无法插入造成的,但未给出具体是哪个字段,分析我们当前的用户数据类型也就只有年龄是数字类型的,但这个有点不太可能,我们输入的确实是数字,其它和数字搭边的就是日期类型了。我们对这两个字段做了排查,结果发现是日期类型DateTime的原因,那为什么会这样呢?我们做一个简单的日期类型输出然后分别在开发机上和Web服务器上去运行试试看,结果如下:

上图第一张是在windows开发机上输出,第二张是在统信UOS上输出。第一个时间是DateTime.Now输出,第二个时间是特定时间输出,主要目的是为区分上下午。很明显看到,在开发机上是24小时格式的,但统信UOS是12小时格式的,并用中文标识出了上午下午,在插入的时候就现了问题,但看了统信UOS时间设置也是24小时制的,网上找了一下,这个问题并不是只是统信UOS独有的,在Linux上都有这个问题,找了一下解决办法,需要在程序开始时设置CultureInfo.DefaultThreadCurrentCulture,我们可以把它加在ProgramMain入口上,代码如下:

public static void Main(string[] args)
{// 跨平台 DateTime 中文 上午 下午 解决方案CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("zh-CN", true){DateTimeFormat = { ShortDatePattern = "yyyy-MM-dd", FullDateTimePattern = "yyyy-MM-dd HH:mm:ss", LongTimePattern = "HH:mm:ss" }};CreateHostBuilder(args).Build().Run();
}

CultureInfo.DefaultThreadCurrentCulture属性用来 获取或设置当前应用程序域中线程的默认区域性,从上面的代码理解是,将其设置中文区域,然后指定了短日期、完整时间以及长时间的格式,这里注意HHhh的区别,HH是24小时制的,而hh是12小时制的。我们在日期输出小例子里加上这一段代码然后再看看其在来个系统统上的输出是怎么样的:

上图第一张是windows开发机,第二张是统信UOS,我们发现时间格式已经和开发机上格式一致了,然后我们再次发布站点,进行测试,问题解决。

小结

通过以上的简单案例,我们实现了在统信UOS操作系统,基于达梦D8数据库,使用.net core 3.1和EntityFramework core的简单增、删、改、查的操作,在这个过程中我们发现windows和Linux类操作系统日期显示格式的不同对我们所开发的应用造成的影响,这个问题应该并不是统信UOS独有的问题。我们当前只是个开端,随着业务的深入,所遇到的问题也将会越来越复杂,具体问题需要具体分析,不管是什么样的问题我们相信都有解决办法。

参考资料

  • DateTime中文上午下午解决方案:https://blog.csdn.net/i2blue/article/details/105798392

  • CultureInfo.DefaultThreadCurrentCulture属性介绍:https://docs.microsoft.com/zh-cn/dotnet/api/system.globalization.cultureinfo.defaultthreadcurrentculture?view=netcore-3.1

  • 在 ASP.NET Core 中使用多个环境:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/environments?view=aspnetcore-3.1

  • EF Core连接达梦数据库参考1:https://blog.csdn.net/lordwish/article/details/104501226

  • EF Core连接达梦数据库参考2:https://blog.csdn.net/lordwish/article/details/108532022

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络知识 | 《图解TCP/IP》读书笔记(下)

【网络知识】| 作者 / Edison Zhou这是EdisonTalk的第291篇原创内容作为一个专业的IT技术人&#xff0c;一个Web应用开发者&#xff0c;不了解网络基础和协议&#xff0c;怎么能行&#xff1f;本文是我2016年阅读《图解TCP/IP》一书的读书笔记下半部分。上半部分&#xff1a;点…

leetcode202. 快乐数(详解)

一:题目 二:上码 class Solution { public:/**思路&#xff1a;1.破解这道题的关键是 我们得破解这个无限循环2.根据这个题目给出的定义2 我们可以知道 无限循环的条件是我们 在计算的过程中出现了自己的数*/bool isHappy(int n) {unordered_set<int>s;s.insert(n);…

自由软件基金会庆祝成立35周年

美国东部时间 10 月 4 日&#xff0c;自由软件基金会&#xff08;Free Software Foundation&#xff0c;FSF&#xff09;在官网发文庆祝”其为争取软件自由而奋斗的第 35 年“。1985 年 10 月&#xff0c;自由软件运动的主要发起人 RMS&#xff08;Richard Matthew Stallman&am…

使用 C# sdk 连接 高可用的 rabbitmq 镜像集群

我们知道rabbitmq是一个专业的MQ产品&#xff0c;而且它也是一个严格遵守AMQP协议的玩意&#xff0c;但是要想高端大气上档次&#xff0c;一定需要拿出高可用的东西出来&#xff0c;这不本篇就跟大家说一下cluster的概念&#xff0c;rabbitmq是erlang写的一个成品&#xff0c;所…

java并发之CyclicBarrier(通俗易懂)

文章目录一:简介(1):官方解释(2):通俗解释a:CountDownLatch()b:CyclicBarrier()二:小demo一:简介 (1):官方解释 说到简介那就非得拿他和countdownlatch()进行比较讨论了CountDownLatch是一个同步的辅助类&#xff0c;允许一个或多个线程&#xff0c;等待其他一组线程完成操作…

BeetleX之简单HTTP/HTTPS实现

在通讯应用中很多时候需要和已有标准的应用协议进行通讯&#xff0c;针对这情况就要针对相应协议的实现&#xff1b;标准协议上考虑的情况比较多&#xff0c;所以协议的复杂度也相对高些&#xff0c;对比之前的Protobuf通讯的简单协议来说则会复杂。接下来用组件去实现一个简单…

体验.NET5 RC1极致性能,你也要“卧槽”!

“ 9月14日&#xff0c;.NET5发布了(Release Candidate)RC1版本&#xff0c;是11月正式版本之前两个RC版本中第一个&#xff0c;包含语言新版本C#9和F#5&#xff0c;需要用Visual Studio 2019 (v16.8, Preview 3)才能使用&#xff0c;注意不是Visual Studio 2019&#xff0c;二…

leetcod383. 赎金信

一:题目 二:上码 class Solution { public:bool canConstruct(string ransomNote, string magazine) {unordered_map<char,int>m;for (auto ch:ransomNote) {m[ch];}for (auto ch: magazine) {if(m.find(ch) ! m.end() && m[ch] > 0) m[ch]--;//当magazine中的…

马斯克推崇的第一性原理,究竟有多重要?

职场&认知洞察 丨 作者 / findyi这是findyi公众号的第79篇原创文章最近&#xff0c;第一性原理这个原本离大众很远的物理概念&#xff0c;被媒体炒的火热。第一性原理最开始是由亚里士多德提出来的。他认为任何一个系统都有一个「第一性原理」。他说&#xff1a;“在每个系…

Gartner 组织世界BI大会,PowerBI 与 Tableau 同台竞技

日前&#xff0c;Gartner 组织了全球顶级 BI 产品大会&#xff0c;由于疫情影响&#xff0c;只能远程举办。官方网址如下&#xff1a;https://blogs.gartner.com/rita-sallam/2020/09/11/bi-bake-off-goes-virtual/该会议的原文为&#xff1a;BI Bake-Off&#xff0c;含义为&am…

leetcode15. 三数之和(详解)

一:题目 二:上码 class Solution { public:/**思路:1.这个题出其不意之处在于,其先对这个序列进行了排序排序的好处是1>:如果首元素是大于0的,那么如果无论无何也凑不出02>:同时我们也把相同的元素凑成一块了 可以方便去重了2.接下来,我们就是利用双指针 来处理 数据是否…

BeetleX之TCP消息通讯Protobuf/TLS

在网络通讯应用中直接操作数据流是比较繁琐的事情&#xff0c;毕竟在业务层面处理的都是对象化消息&#xff1b;为了让网络数据操作变得更友好直观&#xff0c;一般都会引用序列化组件来处理网络流和对象之前的转换工作&#xff1b;在这里介绍组件如何使能Protobuf进行数据交互…

leetcode18. 四数之和

一:题目 二:上码 class Solution { public:/**思路:1.这个跟三数之和差别在于本题加了一层循环,就是我们将第二层循环加在了我们遍历的第一个元素的后面2.其他跟三数之和解题思路一样*/vector<vector<int>> fourSum(vector<int>& nums, int target) {vec…

面试 .NET 开发​,为什么也要考算法?​

最近有不少人面试&#xff0c;我发现很多候选人&#xff0c;聊起架构、框架侃侃而谈&#xff0c;但一写代码&#xff0c;就暴露真实水平。说白了&#xff0c;还是基本功不够扎实。在我看来&#xff0c;所有基本功中&#xff0c;最核心的一定是数据结构与算法。也因此&#xff0…

leetcode344. 反转字符串

一:题目 二:上码 class Solution { public:/**思路:利用双指针来进行处理*/void reverseString(vector<char>& s) {for (int i 0,j s.size()-1; i < j; i,j--) {swap(s[i],s[j]);}} };

跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)

前言撸码需谨慎&#xff0c;裸奔有风险。经常在一些技术交流群中了解到&#xff0c;还有很多小伙伴的项目中Api接口没有做任何安全机制验证&#xff0c;直接就裸奔了&#xff0c;对于一些临时项目或是个人小项目还好&#xff0c;其余的话&#xff0c;建议小伙伴们酌情考虑都加上…

leetcode541. 反转字符串 II

一:题目 二:上码 class Solution { public:/**思路:1.这个我们需要利用到一个库函数 reverse(nums.begin(),nums.end()); // 将字符串反转那么将局部字符串的反转reverse(nums.begin(),nums.begin()2);//表示的是下标左闭右开的 [0,2)2.还有就是在处理每隔2*k这个问题上 我们选…

你是个失败者,有什么资格说话?

这是头哥侃码的第219篇原创这次十一长假&#xff0c;想必有不少朋友和我一样&#xff0c;跟家人聚在一起&#xff0c;吃个饭&#xff0c;喝点小酒&#xff0c;或者吃吃甜点&#xff0c;喝喝下午茶&#xff0c;“享受” 着在疫情严峻形式下难得的宁静时光。两天前&#xff0c;为…

leetcode151. 颠倒字符串中的单词(思路+详解)

一:题目 二:上码 class Solution { public:/**思路:1.去空格(字符串首部的空格 字符串中间的空格 字符串尾部的空格)1>:这里的话 我们就用到了双指针去空格 fastindex遇见空格直接跳过当fastindex遇不见空格&#xff0c;就将值赋值给fastindex;2.字符串反转3.将单词反转*/…

Azure 内容审查器之羞羞图审查

上一篇 Azure 内容审查器之文本审查我们已经介绍了如果使用Azure进行文字内容的审核。对于社区内容&#xff0c;上传的图片是否含有羞羞内容也是需要过虑的。但是最为一般开发者自己很难实现这种级别的智能识别。但是借助Azure的内容审查器可以分分钟实现它。创建内容审查器在使…