日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的時候 并不會生成對應的語句,所以想問問各位大佬,有沒有更好的實現方式.

總結

以上是生活随笔為你收集整理的EFCore3.1+编写自定义的EF.Functions扩展方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。