马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本文基于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继续的,看名称似乎是继续的,其实不是
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|