事值 发表于 2025-5-29 13:14:57

关于EFCore插件API使用中踩过的坑

本文基于efcore8.0,参考文档。
假设需要重写efcore或者特定数据库的方法的SQL转换,按上面文档及其示例代码,本例中我们大概就是提供下面几个接口的实现。

[*]IMethodCallTranslator
[*]IMethodCallTranslatorPlugin
[*]IDbContextOptionsExtension
[*]以及特定数据库的DbContextOptionsBuilder(如SqlServerDbContextOptionsBuilder)扩展方法
后面再说说踩过的坑(总结)!
示例

public class MyMethodCallTranslator:IMethodCallTranslator
{
    private readonly SqlServerSqlExpressionFactory _sqlExpressionFactory;
    public MyMethodCallTranslator(SqlServerSqlExpressionFactory sqlExpressionFactory)
    {
      _sqlExpressionFactory=sqlExpressionFactory
    }
    public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments,IDiagnosticsLogger<DbLoggerCategory.Query> logger)
    {
      //你需要的转换代码,并返回你的SqlExpression
      return null;
    }
}
public class MyMethodCallTranslatorPlugin:IMethodCallTranslatorPlugin
{
    public IEnumerable<IMethodCallTranslator> Translators{get;}
    //坑1:这里注入时不能用SqlServerSqlExpressionFactory,无法解析SqlServerSqlExpressionFactory,只能ISqlExpressionFactory注入后再强转成SqlServerSqlExpressionFactory
    public MyMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory)
    {
      Translators=new List<IMethodCallTranslator>()
      {
            new MyMethodCallTranslator((SqlServerSqlExpressionFactory)sqlExpressionFactory)
      }
    }
}
public class MyDbContextOptionsExtension:IDbContextOptionsExtension
{
    private DbContextOptionsExtensionInfo? _info;
    public virtual void ApplyServices(IServiceCollection services)
    {
      //坑2:必须用new EntityFrameworkRelationalServicesBuilder(services)再添加服务,不能直接用services添加
      new EntityFrameworkRelationalServicesBuilder(services)
            .TryAdd<IMethodCallTranslatorPlugin, MyMethodCallTranslatorPlugin>();
    }
    public virtual DbContextOptionsExtensionInfo Info
      => _info ??= new ExtensionInfo(this);
    public virtual void Validate(IDbContextOptions options)
    {
    }
    private sealed class ExtensionInfo(IDbContextOptionsExtension extension) : DbContextOptionsExtensionInfo(extension)
    {
      public override bool IsDatabaseProvider => false;

      public override int GetServiceProviderHashCode() => 0;

      public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
            => other is ExtensionInfo;

      public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
      {
      }

      public override string LogFragment => "";
    }
}
public static class MySqlServerDbContextOptionsBuilder Extensions
{
    //坑3:这里要用具体数据库的...DbContextOptionsBuilder,用DbContextOptionsBuilder也行,但是就无法注入具体的ISqlExpressionFactory
    //关键是SqlServerDbContextOptionsBuilder不是从DbContextOptionsBuilder继承的,看名称似乎是继承的,其实不是
    public static SqlServerDbContextOptionsBuilder Use...(this SqlServerDbContextOptionsBuilder optionsBuilder)
    {
      var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;

      var extension = coreOptionsBuilder.Options.FindExtension<MyDbContextOptionsExtension>()
            ?? new MyDbContextOptionsExtension();

      ((IDbContextOptionsBuilderInfrastructure)coreOptionsBuilder).AddOrUpdateExtension(extension);

      return optionsBuilder;
    }
}总结

1. ISqlExpressionFactory

注入时不能用SqlServerSqlExpressionFactory,无法解析SqlServerSqlExpressionFactory,只能ISqlExpressionFactory注入后再强转成SqlServerSqlExpressionFactory
2. EntityFrameworkRelationalServicesBuilder

必须用new EntityFrameworkRelationalServicesBuilder(services)再添加服务,不能直接用services添加
3. DbContextOptionsBuilder

这里要用具体数据库的...DbContextOptionsBuilder,用DbContextOptionsBuilder也行,但是就无法注入具体的ISqlExpressionFactory
关键是SqlServerDbContextOptionsBuilder不是从DbContextOptionsBuilder继承的,看名称似乎是继承的,其实不是

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

旁拮猾 发表于 2025-12-12 12:59:40

新版吗?好像是停更了吧。

酝垓 发表于 2025-12-16 19:26:48

这个好,看起来很实用

愤血冒 发表于 2025-12-18 06:45:21

感谢,下载保存了

剧拧并 发表于 2026-1-15 03:29:12

感谢分享

丘娅楠 发表于 2026-1-17 11:07:29

不错,里面软件多更新就更好了

髡芯 发表于 2026-1-21 11:30:21

这个有用。

司空娅玲 发表于 2026-1-21 12:52:57

新版吗?好像是停更了吧。

驳嗦 发表于 2026-1-22 15:01:07

懂技术并乐意极积无私分享的人越来越少。珍惜

玛凶 发表于 2026-1-24 06:34:32

前排留名,哈哈哈

慷规扣 发表于 2026-1-25 10:43:53

很好很强大我过来先占个楼 待编辑

尸酒岐 发表于 2026-1-30 05:22:43

谢谢楼主提供!

荡俊屯 发表于 2026-2-3 22:20:55

谢谢分享,试用一下

皇甫佳文 发表于 2026-2-4 16:26:21

用心讨论,共获提升!

峰襞副 发表于 2026-2-8 01:53:30

收藏一下   不知道什么时候能用到

卜笑 发表于 2026-2-8 12:45:44

热心回复!

寿爹座 发表于 2026-2-8 21:02:25

不错,里面软件多更新就更好了

欤夤 发表于 2026-2-9 17:30:16

感谢分享

僭墙覆 发表于 2026-2-10 07:39:07

喜欢鼓捣这些软件,现在用得少,谢谢分享!

欧阳雪枫 发表于 2026-2-10 13:48:12

谢谢分享,辛苦了
页: [1] 2
查看完整版本: 关于EFCore插件API使用中踩过的坑