本文基于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继承的,看名称似乎是继承的,其实不是
来源链接:https://www.cnblogs.com/pains/p/18839128
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容