EntityFramework Core连接国产达梦数据库

近期意外发现了国产达梦数据库对.NET Core环境下EFCore的支持,把测试过程分享如下。


1.测试环境

  • .Net Core 2.1
  • EntityFramework Core 2.2.4
  • DM v8(达梦)
  • Window 10 x64

2.踩坑记录

近些年数据库等基础设施国产化的呼声越来越高,达梦也算国产数据库中知名度较高的了,不过开发生态环境还不够完善,使用过程中也是各种坑。

2.1达梦数据库的.NET驱动

达梦数据库提供了dotNet、jdbc、odbc等多种驱动方式,在安装目录的drivers目录下都可以找到。市面上找了很久都没有发现.NET Core环境下连接达梦数据库的方案。2019年国内有大牛发布了开源项目FreeSql能够支持达梦数据库,但底层采用的依然是odbc驱动。

在浏览达梦数据库安装目录时意外发现了EFCore.Dm的类库。
在这里插入图片描述
并且在drivers/dotNet目录下的readme文件中也发现这样一段文字。

达梦.Net驱动分为DmProvider、EFDmProvider、EFCore.Dm、DmDialect和DmConnect。
DmProvider可以在.NET框架和NETCore框架下使用,NETCore框架下需要用户安装System.Text.Encoding.CodePages包或者直接以NUGET包的形式安装DmProvider,可以自动依赖的System.Text.Encoding.CodePages包
其中EFDmProvider是支持Entity Framework框架的驱动,它与数据库交互的部分由DmProvider完成,所以如果程序中需要使用EFDmProvider,需要同时引用DmProvider
DmConnect是达梦提供给VS的DDEX驱动,它也引用了DmProvider。
EFCore.Dm已支持EFCore2.1版本
DmDialect方言包有for Nhibernate3、for Nhibernate4、for Nhibernate5分别对应NET3.5、NET4、NET4.6.1;用户可根据开发环境选择对应的方言包版本;
Nhibernate中App.config配置要求:
1、驱动名称
NHibernate.Driver.DmDriver, DmDialect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=072d25982b139bf8
2、方言包名称
NHibernate.Dialect.DmDialect, DmDialect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=072d25982b139bf8
文件结构说明:
DmProvider文件夹中是完整的DmProvider驱动文件。使用DmProvider的DmBulkCopy对象,需要引用dmfldr_dll.dll以及此dll依赖的其他库。
EFDmProvider文件夹中是老版本的EFDmProvider,已不再更新版本。
EFDmProvider6.1.3-net40文件夹中是基于EntityFramework6.1.3及.Net4.0的EFDmProvider 2.0版本。
EFDmProvider6.1.3-net45文件夹中是基于EntityFramework6.1.3及.Net4.5的EFDmProvider 2.0版本。
DmConnect文件夹中是DmConnect驱动及所需文件。
DmDialect文件夹是不同版本NHibernate的方言包
gacutil.exe是全局程序集缓存工具,使用它可以将.Net驱动加载到程序集中。

既然你说你已支持,那就试试。

2.2安装Microsoft.EntityFrameworkCore.Dm

将Microsoft.EntityFrameworkCore.Dm添加到本地的程序包源,使用NuGet管理器安装,失败!

在这里插入图片描述
Internal.AspNetCore.Sdk是什么?打开nupkg文件,猜测就是AspNetCore.SDK的非正式环境,这估计也就解释了为什么这个程序包会藏在这里而在NuGet官方市场上找不到,看来是未完成的测试版了。此处是第一坑。

2.3直接引用类库

无法使用NuGet管理器安装,就根据Microsoft.EntityFrameworkCore.Dm的依赖关系直接引用相关类库。直接在项目中引用“drivers\dotNet\DmProvider\netstandard2.0”目录下的DmProvider.dll和“drivers\dotNet\EFCore.Dm\netstandard2.0”目录下的Microsoft.EntityFrameworkCore.Dm.dll。编译成功。修改数据库连接字符串,启动项目,数据库连接成功。

使用EFCore的CodeFirst模式创建实体类并建立与数据库表的映射关系,执行"update-databse"命令,总是提示“不存在表XXXX”。经过查阅达梦数据库文档才发现,问题可能出在用于登录数据库的用户身上。

在达梦数据库中有模式、登录和用户三个不同的概念,在官方技术论坛上有这样一段描述:

一、登录、用户、模式的定义
登录是相对于数据库服务器而言的,它仅仅代表着连接到数据库实例的权利,但并不代表创建登录就能操作数据库服务器里面的任何数据库(在达梦数据库中,一个数据库实例可以包含多个数据库)。
用户是相对于数据库实例中特定数据库来说的,数据库中的用户拥有对该数据库中指定范围内的对象的操作权利。
模式用来代表特定数据库中的一个对象集,在概念上可将其看作是包含表、视图、索引和权限定义的对象集合。一个模式只作用于一个数据库,不同的数据库可以有同名模式。
二、登录、用户、模式的关系
一个登录可以对应多个不同数据库中的用户,单个数据库中最多只能有一个用户与某一登录对应,没有登录与之对应的用户是没有意义的。一个用户可以创建多个模式,一个模式中的对象(表、视图等)可以被多个用户使用。一个用户可以访问他所属数据库中的任意模式中的对象,只要授予他相应的权限。
为了更好的理解三者之间的关系,下面打个比喻。有一间房(对应一个达梦数据库运行实例),房里有多个保险柜(对应实例中的多个数据库),每个保险柜又有多个抽屉(对应所在数据库中的模式),抽屉里存放一些贵重的物品(对应数据库中的某个模式下的表、视图等数据实体)。
我们要进入房间需要房间的钥匙(对应登录名),进入房间后我们要打开保险柜需要保险柜的钥匙(对应用户名),并且进入房间并不代表我们可以打开保险柜,我们只有是某一保险柜的使用用户才能打开保险柜,以一个登录身份进入房间后,我们可能是多个保险柜的使用用户,这样我们有可能可以打开多个保险柜(一个登录可以对应多个不同数据库中的用户)。对保险柜而言,不同的用户身份对应保险柜中不同的抽屉,打开保险柜后,依据用户身份的不同,决定用户所能使用的抽屉,保险柜的一个用户可以使用多个抽屉,一个抽屉也可能被多个用户使用(一个用户可以创建多个模式,一个模式中的对象可以被多个用户使用)。

简单消化了上述文字,检查数据库发现用到的用户被锁定了,修改了用户选项,错误消失。此处是第二坑。

2.4 .NET Core 2.x环境

上面的错误消失了,又一个新的错误出现了。

“Method ‘get_Info’ in type ‘Microsoft.EntityFrameworkCore.Dm.Infrastructure.Internal.DmOptionsExtension’ from assembly ‘Microsoft.EntityFrameworkCore.Dm, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60’ does not have an implementation”

大意就是某个方法没实现,思来想去又从头检查了一遍,才发现是自己坑了自己。原来是我创建项目是默认选择了.NET Core 3.1的开发环境,人家说的是支持.NET Core 2.1,错误原因就在这里。将项目改成了.NET Core 2.1,重新编译项目,执行EFCore命令,数据表成功被创建!继续测试了其他功能,查询没有问题,插入、更新、删除都还存在问题,原因正在查找中。


2-25补充

继续测试,更换多个版本的EntityFramework Core(仅限于2.x版本),插入、更新、删除均报错,详细信息如下:

System.MissingMethodException: Method not found: 'Dm.DmTransaction Dm.DmConnection.BeginTransaction(System.Data.IsolationLevel)'.
         at Microsoft.EntityFrameworkCore.Dm.Storage.Internal.DmRelationalConnection.BeginTransactionWithNoPreconditions(IsolationLevel isolationLevel, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Dm.Storage.Internal.DmRelationalConnection.BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionAsync(CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Dm.Storage.Internal.DmExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entriesToSave, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

基本可以证明达梦8的.NET驱动EFCore.Dm存在BUG,尚未完成,不能使用。

还望达梦官方能早日更新,完善生态,造福广大开发者!


2-28再次补充

发给达梦官方的邮件今天有回复了,说是支持EFCore3.1驱动正在开发中,就让我们翘首以待吧!

参考资料:

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在使用Winform和Entity Framework Core进行多数据库操作时,我们需要注意以下几个方面。 首先,需要在项目中引入Entity Framework Core的相关包。 接下来,在创建DbContext时,我们需要根据具体的数据库类型(例如MySQL、SQL Server等)来选择不同的数据库提供程序。可以通过在DbContext的构造函数中传入相应的数据库连接字符串来实现。 在操作数据库时,可以使用Entity Framework Core提供的数据库迁移功能来自动创建数据库表和更新数据库结构。通过运行`add-migration`和`update-database`命令,可以根据实体类的变化来自动创建表和更新数据库。 在多数据库操作时,我们需要为每个数据库定义独立的DbContext,并在业务代码中根据具体需求使用不同的DbContext进行操作。 需要注意的是,在使用多数据库时,我们还需要考虑事务管理的问题。可以使用Entity Framework Core提供的`Database.BeginTransactionAsync`方法来开启一个事务,然后在事务中执行多个数据库操作。 另外,为了便于管理和维护代码,我们可以将操作不同数据库的代码封装为不同的服务或仓储类,并使用依赖注入来注入具体的实现。这样可以提高代码的可读性和可维护性。 总结来说,使用Winform和Entity Framework Core进行多数据库操作需要注意选择合适的数据库提供程序、定义独立的DbContext、使用数据库迁移来管理数据库结构、注意事务管理,并将代码进行封装和依赖注入,以提高代码的可读性和可维护性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值