EFCore3.1+编写自定义的EF.Functions扩展方法

前言

本文主要是讲解EF Core3.0+ 如何实现自定义的数据库扩展函数,虽然EF.Functions 提供了很多数据库函数,但是并不全面.比如加密解密..。这样的话 我们就需要自己扩展这些数据库函数 从而达到调用的目的.

本文以达梦数据库为例(其他数据库都一样)..

上篇文章推荐: EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录

 

正文

1.创建扩展方法

首先我们需要创建自定义的扩展方法如下:

 public static class DbFunctionsExtensions{/// <summary>/// 调用数据库的加密方法/// </summary>/// <param name="_"></param>/// <param name="context"></param>/// <param name="typeid"></param>/// <param name="key"></param>/// <returns></returns>public static string DmAlgorithmsEncrypt(this DbFunctions _, string context, int typeid, string key){throw new InvalidOperationException("该方法仅用于实体框架核心,没有内存实现。");}/// <summary>/// 调用数据库的解密方法/// </summary>/// <param name="_"></param>/// <param name="context"></param>/// <param name="typeid"></param>/// <param name="key"></param>/// <returns></returns>public static string DmAlgorithmsDecrypt(this DbFunctions _, string context, int typeid, string key){throw new InvalidOperationException("该方法仅用于实体框架核心,没有内存实现。");}

很简单,我们只需要定义2个静态扩展方法,并且抛出一个InvalidOperationException异常即可.

2.创建调用方法转换器(IMethodCallTranslator)

这里记住IMethodCallTranslator这个接口,我们需要实现它,如下:

 public class DmDbFunctionsTranslateImpl : IMethodCallTranslator{private readonly ISqlExpressionFactory _expressionFactory;private static readonly MethodInfo _dmAlgorithmsEncryptMethod= typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.DmAlgorithmsEncrypt),new[] { typeof(DbFunctions), typeof(string), typeof(int), typeof(string) });private static readonly MethodInfo _dmAlgorithmsDecryptMethod= typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.DmAlgorithmsDecrypt),new[] { typeof(DbFunctions), typeof(string), typeof(int), typeof(string) });public DmDbFunctionsTranslateImpl(ISqlExpressionFactory expressionFactory){_expressionFactory = expressionFactory;}public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments){ //判断方法是否一致if (method == _dmAlgorithmsEncryptMethod){var args = new List<SqlExpression> { arguments[1], arguments[2], arguments[3] };return _expressionFactory.Function(instance, "CFALGORITHMSENCRYPT", args, typeof(string));}if (method == _dmAlgorithmsDecryptMethod){var args = new List<SqlExpression> { arguments[1], arguments[2], arguments[3] };return _expressionFactory.Function(instance, "CFALGORITHMSDECRYPT", args, typeof(string));}return null;}}

3.创建调用转换器提供程序(RelationalMethodCallTranslatorProvider)

 public sealed class DmAlgorithmsMethodCallTranslatorPlugin : RelationalMethodCallTranslatorProvider{public DmAlgorithmsMethodCallTranslatorPlugin(RelationalMethodCallTranslatorProviderDependencies dependencies): base(dependencies){ISqlExpressionFactory expressionFactory = dependencies.SqlExpressionFactory;AddTranslators(new IMethodCallTranslator[]{//这里,将刚刚的方法转换器添加到扩展new DmDbFunctionsTranslateImpl(expressionFactory)});}}

这个类主要是将我们刚刚创建的方法转换器添加SQL表达式工厂(SqlExpressionFactory)当中.

 

4.创建DbContext扩展类(IDbContextOptionsExtension)

代码如下,关键点加了注释,自行参考..

 public class DmDbContextOptionsExtension : IDbContextOptionsExtension{private DbContextOptionsExtensionInfo _info;public void Validate(IDbContextOptions options){}public DbContextOptionsExtensionInfo Info{get{return this._info ??= new MyDbContextOptionsExtensionInfo(this);}}void IDbContextOptionsExtension.ApplyServices(IServiceCollection services){//这里将转换器注入到服务当中.services.AddSingleton<IMethodCallTranslatorProvider, DmAlgorithmsMethodCallTranslatorPlugin>();}private sealed class MyDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo{public MyDbContextOptionsExtensionInfo(IDbContextOptionsExtension instance) : base(instance) { }public override bool IsDatabaseProvider => false;public override string LogFragment => "";public override void PopulateDebugInfo(IDictionary<string, string> debugInfo){}public override long GetServiceProviderHashCode(){return 0;}}}

5.创建DbContext生成时的扩展方法

    public static class DmDbContextOptionsBuilderExtensions{public static DbContextOptionsBuilder UseDmAlgorithmsEncryptionFunctions(this DbContextOptionsBuilder optionsBuilder){//将自定义的配置类添加到配置选项中var extension = GetOrCreateExtension(optionsBuilder);((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);return optionsBuilder;}//生成创建扩展类private static DmDbContextOptionsExtension GetOrCreateExtension(DbContextOptionsBuilder optionsBuilder)=> optionsBuilder.Options.FindExtension<DmDbContextOptionsExtension>()?? new DmDbContextOptionsExtension();}

 

6.编写测试代码,查看使用效果

我们先在数据库插入一条加密数据如下:

insert into "tab"."tab"( "XingMing", "ZhengJianHao", "ShouJiHao") 
VALUES( '测试数据1', CFALGORITHMSENCRYPT('123456789',514,'ABC'),'77777');

 

然后我们编写查询代码:


var ddd= Context.Where(a => EF.Functions.DmAlgorithmsDecrypt(a.ZhengJianHao, 514, "ABC") == "123456789").First();

 这里,我们将数据解密后在对比

查询效果如下:

 

我们通过监控SQL语句 可以看到如下SQL语句:

 

 这里,已经将我们的自定义扩展函数转换成了SQL函数 并在数据库执行了.

写在最后

这里我们就完成了整个SQL函数的扩展. 写这篇主要是为了抛砖引玉..

目前这种扩展方式,在查询的时候 可以正常的生成SQL语句,

但是在ADD 和Update的时候 并不会生成对应的语句,所以想问问各位大佬,有没有更好的实现方式.

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

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

相关文章

WSUS2.0数据导入、导出(备份、还原)

以前我们做的WSUS实验都是让WSUS服务器通过互联网连接到微软网站去下 载更新补丁&#xff0c;但是现实的生活中有些网络是与互联网隔绝的&#xff0c;这种情况下可以采用导入导出WSUS数据的方法来解决WSUS的更新问题。先在一台能联网的 WSUS服务器上下载所需更新&#xff0c;然…

linux perl模块检测,Linux有问必答:如何用Perl检测Linux的发行版本

提问:我需要写一个Perl程序&#xff0c;它会包含Linux发行版相关的代码。为此&#xff0c;Perl程序需要能够自动检测运行中的Linux的发行版(如Ubuntu、CentOS、Debian、Fedora等等)&#xff0c;以及它是什么版本号。如何用Perl检测Linux的发行版本&#xff1f;如果要用Perl脚本…

NET问答: 如何将 ASP.NET Core WebAPI 中抛出的异常封装成对象?

咨询区 rianjs&#xff1a;在 ASP.NET Core WebAPI 中&#xff0c;我的 Controller 代码如下&#xff1a;[Route("create-license/{licenseKey}")] public async Task<LicenseDetails> CreateLicenseAsync(string licenseKey, CreateLicenseRequest license) {…

借助TensorFlow框架,到底能做什么?

谷歌在七月份正式推出了深度学习框架TensorFlow 1.9 版本&#xff0c;那么TensorFlow框架到底是什么&#xff1f;TensorFlow™ 是一个采用数据流图&#xff08;data flow graphs&#xff09;&#xff0c;用于数值计算的开源软件库。最初由Google大脑小组的研究员和工程师们开发…

在c语言中如何屏蔽一段程序,如何在用C语言关闭TCP程序中的Nagle算法

TCP为了防止在网络中过多的小分组会导致阻塞&#xff0c;因此提供了Nagle算法&#xff1a;要求一个TCP连接上最多只能有一个未被确认的未完成的小分组&#xff0c;在该分组的确认到达之前不能发送其他的小分组。相反&#xff0c;TCP收集这些少量的分组&#xff0c;并在确认到来…

CCNP课堂练习四:frame-relay traffic-shaping(帧中继流量×××)

帧中继(Frame Relay)是一种网络与数据终端设备(DTE)接口标准。它可以减少结点的处理时间,提高网络的吞吐量。帧中继提供的是数据链路层和物理层的协议规范,任何高层协议都独立于帧中继协议,因此,大大地简化了帧中继的实现。目前帧中继的主要应用之一是局域网互联,特别是在局域网…

百度内部培训PPT流出:数据分析的道与术

这是一份来自百度内部的数据分析学习PPT&#xff0c;非常经典的入门教材。主要内容1、什么是数据分析&#xff08;道&#xff09;1.1 数据分析是什么&#xff1f;1.2 什么是做好数据分析的关键&#xff1f;1.3 分析要思考业务&#xff0c;尤其是接地气1.4 分析要言之有物&#…

C语言程序设计答案黄保和编,C语言程序设计答案(黄保和编)第5章.pdf

厦门大学本科生公共课 《C 程序设计基础》 教材习题答案 第五章 循环结构程序设计一、选择题1.设有程序段”int k10;while(k0)kk-1;”&#xff0c;则下面叙述正确的是D 循环体语句一次也不执行2.设有程序段”int x0,s0;while(!x!0)sx;printf(“%d”,s);”则A 运行程序段后输出1…

VS2010 C++下编译调试MongoDB“.NET研究”源码

考虑到mongodb使用了boost库源码&#xff0c;参考mongodb官方文档后&#xff0c;下载编译boost版本是1.42(时间为2010-2-2)或更新版本:boost版本1.42&#xff1a;http://sourceforge.net/projects/boost/files/boost/1.42.0/boost_1_42_0.zip/download 下载boost源码之后…

有了这15款编程游戏,谁都可以学编程!

1、Coding Games一边玩游戏&#xff0c;一边挑战编程难题。Coding games支持包括PHP、C、JavaScript在内的20多种编程语言。用户界面功能强大&#xff0c;可以定制。例如&#xff0c;你可以选择你的代码编辑器的风格&#xff1a; Emacs、Vim、Classic。如果你想提升编程技能&am…

C# 封装

封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中"。在面向对象程序设计方法论中&#xff0c;封装是为了防止对实现细节的访问。抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化&#xff0c;封装则使开发者实现所需级别的抽象。C# 封…

C语言中比较大小的函数模板,C语言中实现模板函数小结 : 不敢流泪

—-by boluor 2009/5/20如果要写个函数支持多种数据类型&#xff0c;首先想到的就是C的模板了&#xff0c;但是有时候只能用C语言&#xff0c;比如在linux内核开发中&#xff0c;为了减少代码量&#xff0c;或者是某面试官的要求…考虑了一阵子后&#xff0c;就想到了qsort上.q…

lamp架构优化

LAMP&#xff08;LinuxApacheMysqlPerl/PHP/Python&#xff09;常用来搭建动态网站或者服务器的开源软件&#xff0c;本身都是各自独立的程序&#xff0c;但是因为常被放在一起使用&#xff0c;拥有了越来越高的兼容度&#xff0c;共同组成了一个强大的Web应用程序平台。每个LA…

毕业的那天,程序员师兄竟然让我去做这一行

给大家看一份最新的数据&#xff1a;&#xff08;薪资表&#xff09;2018年最新数据&#xff1a;python、大数据、人工智能从业者工资为什么人工智能行业的工资那么高&#xff1f;无论是科研院所&#xff0c;商业巨头还是初创企业&#xff0c;各行各业都在大力开发或者引进人工…

C# FileSystemWatcher文件监控实例

FileSystemWatcher可以使用FileSystemWatcher组件监视文件系统&#xff0c;并对文件系统的改变作出反应。通过使用FileSystemWatcher组件&#xff0c;在特定的文件或目录被创建、修改或删除时&#xff0c;可以快速和便捷地启动业务流程。例如&#xff0c;如果一组用户在合作处理…

c语言中二重指针如何赋值,关于二重指针释放的有关问题

关于二重指针释放的问题使用 malloc 来申请内存&#xff0c;申请的代码部分如下&#xff1a;float *fp (float*)malloc(sizeof(float)* h * w);float **cost (float**)malloc(sizeof(float*)* h);for (int i 0; i cost[i] &fp[i * w];}那我释放的时候应该如何释放呢&am…

第一个Win32 SDK应用程序

#include<windows.h>int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int);LRESULT WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);// WinMain 函数int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){HWND hWnd; // 主窗口句柄…

Python 分析《爱情公寓》电影,让我十年情怀一瞬间都喂了狗

深陷抄袭之名、诉讼纠纷的《爱情公寓》终于上映了。情怀粉们的力量不容小觑&#xff0c;截止到8月12&#xff0c;《爱情公寓》票房已经突破3.72亿大关&#xff0c;稳坐票房冠军的宝座&#xff0c;院线排片占比高达40.0%。和超高票房背道而驰的&#xff0c;是各大社交平台上一边…

银行背景下分库分表技术选型

业务持续增长带来的单表数据量过大&#xff0c;必然影响到数据库的读写性能&#xff0c;那到底要不要分库分表呢&#xff1f;阿里巴巴P3C规范给出一个推荐&#xff1a;【推荐】单表行数超过500万行或者单表容量超过2GB&#xff0c;才推荐进行分库分表。说明&#xff1a;如果预计…

单片机矩阵消抖延时c语言,单片机矩阵按键定时器消抖程序源码

芯片是采用的stc89c51单片机.下面是矩阵键盘的电路图&#xff0c;矩阵键盘是接在p2口的.下面是单片机部分的图,数码管显示等完整的原理图可以从http://www.51hei.com/f/ks51.pdf 这里下载本文引用地址&#xff1a;http://www.eepw.com.cn/article/201612/324612.htm下面是程序源…