The tracing and caching providers (or here) provide an excellent way to trace and cache EF queries. Unlike those that attempt to do the same above the EF API, these providers work under the covers and make tracing and caching non-invasive for the application code. Specifically, for cases where entities are lazy-loaded via EF and those entities are to be cached, this caching provider is truly more advantageous.
However, these providers were written before EF 4.1 code first and they wouldn't work if you just follow the old sample. Luckily, it is not too difficult to make them work. The trick is to create a wrapping EFCachingConnection or EFTracingConnection that wraps a DbConnection (such as SqlConnection) and pass it to the DbContext constructor. I will just demonstrate the caching related code here but you should be able to chain tracing, caching and then the underlying SqlConnection using the same pattern.
First, a minor modification to the EFCachingConnection constructor is needed. As shown in the following code, we need to be able to set the wrappedProviderInvariantName via the ctor:
- public EFCachingConnection(DbConnection wrappedConnection, string wrappedProviderInvariantName)
- {
- this.WrappedConnection = wrappedConnection;
- this.CachingPolicy = EFCachingProviderConfiguration.DefaultCachingPolicy;
- this.Cache = EFCachingProviderConfiguration.DefaultCache;
- base.wrappedProviderInvariantName = wrappedProviderInvariantName; // make it possible to set the wrappedProviderInvariantName via this ctor
- }
The I use the following helper function to create an instance of the EFCachingConnection that wraps a SqlConnection:
- public static EFCachingConnection CreateEFCachingConnectionWrapper(string nameOrConnectionString)
- {
- string connectionString;
- if (nameOrConnectionString.Contains("="))
- connectionString = nameOrConnectionString;
- else
- connectionString = ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString;
- DbConnection connection = new SqlConnection(connectionString);
- return new EFCachingConnection(connection, "System.Data.SqlClient");
- }
Now you would simply pass the newly constucted EFCachingConnection instance to the ctor of DbContext:
- public MyContext(DbConnection connection)
- : base(connection, true)
- {
Note that MyContext is the application's EF code first context, which derives from DbContext and has probably overriden the OnModelCreating() method.
Last and not the least you would need to call EFCachingProviderConfiguration.RegisterProvider() first when you start your application.
Happy holidays and happy EF coding!