Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save swax/39e1b3ba83dadaf787a45a24bf82c6de to your computer and use it in GitHub Desktop.
Save swax/39e1b3ba83dadaf787a45a24bf82c6de to your computer and use it in GitHub Desktop.
EntityFramwork DbConfiguration with custom DbModelStore for loading cached db models. Fork: Instead of invalidating based on date, this version invalidates based on the hash of the model assembly.
public class MyContextConfiguration : DbConfiguration
{
public MyContextConfiguration()
{
HashedDbModelStore cachedDbModelStore = new HashedDbModelStore(MyContext.EfCacheDirPath); // possibly c:\temp\efcache
IDbDependencyResolver dependencyResolver = new SingletonDependencyResolver<DbModelStore>(cachedDbModelStore);
AddDependencyResolver(dependencyResolver);
}
/// <summary>
/// Store and load based on the hash of the model so that rebuilds, switching branches,
/// and ASP deployments do not invalidate what is essentially the same model
/// </summary>
private class HashedDbModelStore : DefaultDbModelStore
{
public HashedDbModelStore(string location)
: base(location)
{ }
public override DbCompiledModel TryLoad(Type contextType)
{
try
{
Trace.WriteLine("Context location: " + contextType.Assembly.Location);
var cachedPath = GetFilePath(contextType);
Trace.WriteLine("Cached context location: " + cachedPath);
if (File.Exists(cachedPath))
{
Trace.WriteLine("Cached context found!");
}
else
{
// delete out of date cached contexts
var prefix = GetFilePrefix(contextType);
foreach (var filepath in Directory.GetFiles(Location))
if (filepath.StartsWith(prefix))
File.Delete(filepath);
Trace.WriteLine("Cached context not found, creating...");
}
}
catch (Exception ex)
{
Trace.WriteLine("Exception trying to load cached EF model: " + ex.Message);
}
return base.TryLoad(contextType);
}
protected override string GetFilePath(Type contextType)
{
var prefix = GetFilePrefix(contextType);
var hash = GetContextAssemblyHash(contextType);
var filename = prefix + hash + ".edmx";
return Path.Combine(Location, filename);
}
private string GetFilePrefix(Type contextType)
{
return Path.GetFileNameWithoutExtension(contextType.Assembly.Location) + "-";
}
/// <summary>
/// MD5 because we need something quick and unique, no security issues here
/// </summary>
private string GetContextAssemblyHash(Type contextType)
{
using (var md5 = MD5.Create())
using (var stream = File.OpenRead(contextType.Assembly.Location))
{
var hashBytes = md5.ComputeHash(stream);
var sb = new StringBuilder();
foreach (byte bt in hashBytes)
sb.Append(bt.ToString("x2"));
return sb.ToString();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment