2

I'm looking for a way to intercept database queries as a means of getting some more in-depth performance stats. I'm after number of queries, query duration, the result data (for an idea of data magnitude) and ideally some access to any LINQ expression.

I can fall back on extending a base context class, creating another method to get DbSet, returning a wrapper there, but 1) that seems hackier than it ought to be, 2) any code there won't be able to distinguish getting cached results vs actual database accesses..

I've looked through the code and feel like wrapping ExecutionStrategyFactory or Database is the way to go - and while I can create an extension method on RelationalDbContextOptionsBuilder for the former, or /replace/ services, I can't see a way of wrapping either, such that the underlying provider's implementation is still used.

(See also: https://github.com/aspnet/EntityFramework/issues/6967)

Is there a decent place to hook into this?

STW
  • 44,917
  • 17
  • 105
  • 161
Kieren Johnstone
  • 41,277
  • 16
  • 94
  • 144

1 Answers1

1

For the ref of anyone else:

Ok, the trick is:

  1. Replace the IRelationalConnection that EF Core's DI system uses via ReplaceService<IRelationalConnection, MyRc>(). Our new MyRc will wrap the existing connection to add hooks
  2. In our MyRc, have a constructor param of IDatabaseProviderServices. The EF DI system will populate it. Cast that to IRelationalDatabaseProviderServices and then grab the RelationalConnection property from that
  3. Wrap all methods, but have public DbConnection DbConnection { get; } return an instance of a DbConnection-wrapping class
  4. In that wrapping class, have CreateDbCommand() return an instance of a DbCommand-wrapping class
  5. In that wrapping class, have ExecuteDbDataReader() return an instance of a DbDataReader-wrapping class

Then, in the DbCommand and DbDataReader wrappers, we can see what commands and parameters are being sent to the database, and the results coming back.

This only works with relational models.

Kieren Johnstone
  • 41,277
  • 16
  • 94
  • 144