网上最多就是类似于在 IQueryable 上面扩展方法,这样只能获取查询列表的SQL 语句,但如果 我是查
_dbContext.Set<T>().AsNoTracking().FirstOrDefaultAsync(predicate);
这样,我只能使用
_dbContext.Set<T>().AsNoTracking().ToQueryString();
来获取SQL语句,这个 ToQueryString 方法并没有 sql语句的 where 部分语句,也就是没有条件。只生成了 select 字段列表 from 表。
我想的是能不能获取到的 SQL 语句 ,跟在 Sql Server Profiler 一样。 或者像 SqlSugar一样支持 Ado 切面。但现在 EF core 好像是没有办法的。
var db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = ConnStr,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute
});
//sql执行前
db.Aop.OnLogExecuting = (sql, pars) =>
{
Debug.WriteLine("SQL执行前==>>>" + sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
if (db.TempItems == null) db.TempItems = new Dictionary<string, object>();
};
//sql执行后
db.Aop.OnLogExecuted = (sql, pars) =>
{
Debug.WriteLine("SQL执行后==>>>" + sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
};
//sql执行错误
db.Aop.OnError = (pars) =>
{
};
有很多中方法实现
1、自定义DbCommandInterceptor
2、自定义Logger,在输出日志中拦截处理
刚想到了拦截器,我主要是想和zipkin做集成。有没有其它的实现方法呢,能不能给我个参考
@暖暖De幸福: zipkin没用过
https://docs.microsoft.com/en-us/ef/core/logging-events-diagnostics/
@通信的搞程序: zipkin已经部分已经实现了,只差拿到SQL语句。谢谢老师。我就直接用拦截器来实现了。
貌似不需要,可以直接打印在console里面
我是想把一些超过一定时间的查询给记录到日志里面的。
@暖暖De幸福: 那就要自己写代码了
我在以前ef2.0的时候通过下面的代码对 IQueryable<TEntity>
扩展是可以的。
尝试一下以下代码:
public static class QueryableExtensions
{
private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");
private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.First(x => x.Name == "_queryModelGenerator");
private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
private static readonly PropertyInfo DatabaseDependenciesField = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies");
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
var queryCompiler = (QueryCompiler)QueryCompilerField.GetValue(query.Provider);
var modelGenerator = (QueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler);
var queryModel = modelGenerator.ParseQuery(query.Expression);
var database = (IDatabase)DataBaseField.GetValue(queryCompiler);
var databaseDependencies = (DatabaseDependencies)DatabaseDependenciesField.GetValue(database);
var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false);
var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
var sql = modelVisitor.Queries.First().ToString();
return sql;
}
}
如果是扩展到 IQueryable 上面,我单个实体的查询语句不能用。
@暖暖De幸福: 说的离谱,单个实体查询啥不能用???
@Jonny-Xhl:你这段代码,我网上一搜就是,如果能用,我还来这里问???