Forked from davidroth/EntityFramwork DbModelStore for loading cached db models.
Last active
March 18, 2017 23:01
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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