悄悄的,达梦数据库的EFCore驱动更新了。
在经过今年2月份对达梦数据库的EFCore驱动测试后,发现还是存在一些问题的,官方回应称会在后续版本中完善。在8月份的时候安装了最新版本的达梦8,发现EFCore驱动在7月下旬已经悄悄更新了,也是最近才抽出时间来进行测试。下面就是本次测试血与泪的过程记录。
1.测试环境
- .NET Core 3.1
- EntityFrameworkCore 3.1
- Windows 10 x64 专业版
- DM v8(达梦)
- ABP v5.9(.NET Core 3.x版)
本次测试环境由.NET Core 2.1改成了NET Core 3.1,并且使用了比较流行的开发框ABP进行测试,接近真实开发环境,更能反映实际问题。
2.测试过程
2.1安装达梦数据库的EFCore驱动
驱动仍然是在安装目录的deivers目录下,只不过这次dotnet驱动增加了EFCore3.1版本。
仍然是没有公开发行到官方NuGet源上,只能手动上传到本地私有NuGet源,然后安装到代码项目中。
2.2修改数据库相关配置
修改代码项目中的数据库相关配置,由于使用ABP框架进行测试已经内置了EFCore,而且ABP框架以仓储的形式对数据库相关操作进行了封装,改动比较少的代码就能从常用的MySQL、SQLServer连接改为达梦数据库连接。
在基础设施层将连接改为达梦数据库
public static class DbContextOptionsConfigurer
{
public static void Configure(
DbContextOptionsBuilder<AbpDemoDbContext> dbContextOptions,
string connectionString
)
{
/* 配置数据库连接上下文 */
//SQL Server
//dbContextOptions.UseSqlServer(connectionString);
//MySql
//dbContextOptions.UseMySql(connectionString);
//DM
dbContextOptions.UseDm(connectionString);
}
}
同样在配置文件appSetting.json中修改数据库连接字符串
"ConnectionStrings": {
"Default": "Server=127.0.0.1:5236;UID=SYSDBA;PWD=SYSDBA;"
}
之后开始常用增删改查操作的测试。
3.问题记录及解决
3.1.打开数据库连接失败
第一步就来了个下马威,数据库竟然连接不上,IP地址没问题,用户存在,密码也没错,问题出在哪里?
检查了好一会儿才发现还是对达梦数据库的结构理解不到位,在之前的文章中也提到过达梦使用的是登录、用户、模式的结构。以MySQL为例,一个用户下面可以有多个数据库,root用户下可以见A、B、C三个库,连接字符串写“Server=xxx;DataBase=A;User=root;Password=PWD;”即可。而达梦是一个用户下面可以有多个模式,SYSDBA下可以有D、E、F三个模式,想要访问D模式就需要在查询语句的表名前面加上模式名,然而达梦的数据库连接字符串并不支持这么些。所以通常做法是创建D、E、F三个用户,然后分别创建D、E、F三个模式分给用户,让用户和模式名称一样,就能访问了。
由于我是使用达梦迁移工具将原有MySQL的数据库迁移到达梦数据库,默认是迁移到DBO模式下,然而达梦并没有DBO这个用户,导致连接不上。创建同名的用户和模式后问题就解决了。
3.2.找不到对应的表或字段
数据库连接问题解决后,可以通过WebAPI接口对增删改查操作进行测试了,然而执行后却发现“表xxx不存在”。数据库连接成功,表却不存在,什么问题?
检查之后发现还是配置的问题,达梦数据库默认是大写的,而之前的代码是连结过MySQL和SQL Server的,表名既有大写字母又有小写字母。两边对应不上自然就找不到表了。
还好ABP框架中可以修改实体与数据库表的映射关系,将映射的表名改为大写即可。
此外也可在安装达梦数据库时选择“是否大小写敏感”为“否”,同样能解决问题。
3.3.试图在只读事务中修改数据
上面两个问题解决后可以查到数据了,然而事情没那么简单,进行新增、修改、删除操作时报错了。
这个问题就很奇怪了,首先同样的代码连接过MySQL和SQL Server运行正常,其次不使用封装过的仓储模式而是用简单的控制台项目可以进行新增、修改、删除操作。本来以为又是达梦提供的驱动有问题,仔细排查下来感觉可能是ABP框架中仓储的问题。查了相关资料,发现可以在ABP框架中使用非事务性的工作单元,这样问题就能解决了。
在相应的方法上添加属性标记用来近用数据库级事务。
[UnitOfWork(isTransactional: false)]
public Task Create()
{
}
也可以在模块的预加载方法中在全局禁用数据库事务。
经过以上测试,增删改查这些常用业务操作基本没问题了。然而禁用事务并不是一个最佳的方案,还是要寻找更好的解决方法。
测试国产达梦数据库的过程可谓是坑坑不断、惊喜连连,满含血与泪的经验。顺便吐槽一下,公开资料匮乏、技术论坛崩溃、开发者生态薄弱,国产数据库想要“达梦”仍是漫漫长路。