首页 » 后端 » C# EF的DbConfiguration加载优化
using System.Data.Entity.ModelConfiguration.Configuration; using System.Linq; using System.Collections.Generic; namespace TestCase.EntityFramework { public class TestCaseDBConfig : DbConfiguration { private static string EFFoldPath = ""; public TestCaseDBConfig() : base() { SetProviderServices("System.Data.SqlClient", System.Data.Entity.SqlServer.SqlProviderServices.Instance); EFFoldPath = AppDomain.CurrentDomain.BaseDirectory + "App_Data\\EFCache"; if (!Directory.Exists(EFFoldPath)) Directory.CreateDirectory(EFFoldPath); TestCaseDbModelStore cachedDbModelStore = new TestCaseDbModelStore(EFFoldPath); IDbDependencyResolver dependencyResolver = new SingletonDependencyResolver<DbModelStore>(cachedDbModelStore); AddDependencyResolver(dependencyResolver); } private class TestCaseDbModelStore : DefaultDbModelStore { public TestCaseDbModelStore(string location) : base(location) { } public override XDocument TryGetEdmx(Type contextType) { return LoadXml2(contextType, XDocument.Load); } private void GetConceptualAssociationNames(List<System.Data.Entity.Core.Metadata.Edm.AssociationType> lstAssociationTypes, List<string> lstNames) { int oldCount = lstNames.Distinct().ToList().Count; foreach (var association in lstAssociationTypes) { if (association.AssociationEndMembers != null && association.AssociationEndMembers.Count > 0) { var isAssociaEsixt = association.AssociationEndMembers.Where(a => lstNames.Contains(a.GetEntityType().Name)).FirstOrDefault() != null; if (isAssociaEsixt) { if (!lstNames.Contains(association.Name)) lstNames.Add(association.Name); foreach (var endMember in association.AssociationEndMembers) { if (!lstNames.Contains(endMember.GetEntityType().Name)) lstNames.Add(endMember.GetEntityType().Name); } } } } if (oldCount != lstNames.Distinct().Count()) { GetConceptualAssociationNames(lstAssociationTypes, lstNames); } } public override void Save(Type contextType, DbModel model) { if (contextType.GenericTypeArguments != null && contextType.GenericTypeArguments.Length > 0) { string name = contextType.GenericTypeArguments[0].Name; List<string> storeModelNames = new List<string>(); storeModelNames.Add(name); storeModelNames.Add("Entities"); #region StoreModel List<string> storeModelAssociates = new List<string>(); if (model.StoreModel.AssociationTypes != null && model.StoreModel.AssociationTypes.Count() > 0) { GetConceptualAssociationNames(model.StoreModel.AssociationTypes.ToList(), storeModelNames); var removedStoreAssociates = model.StoreModel.AssociationTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedAssociate in removedStoreAssociates) { var tmp = model.StoreModel.AssociationTypes.Where(a => a.Name == removedAssociate.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.RemoveItem(tmp); } } } storeModelNames = storeModelNames.Distinct().ToList(); var removedStoreModels = model.StoreModel.EntityTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedStoreModel in removedStoreModels) { var tmp = model.StoreModel.EntityTypes.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.RemoveItem(tmp); } } var removeEntitySetBase = model.StoreModel.Container.BaseEntitySets.Where(a => !storeModelNames.Contains(a.ElementType.Name)).ToList(); foreach (var removedStoreModel in removeEntitySetBase) { var tmp = model.StoreModel.Container.BaseEntitySets.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.Container.RemoveEntitySetBase(tmp); } } #endregion #region ConceptualModel List<string> conceptualAssociates = new List<string>(); if (model.ConceptualModel.AssociationTypes != null && model.ConceptualModel.AssociationTypes.Count() > 0) { GetConceptualAssociationNames(model.ConceptualModel.AssociationTypes.ToList(), storeModelNames); var removedStoreAssociates = model.ConceptualModel.AssociationTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedAssociate in removedStoreAssociates) { var tmp = model.ConceptualModel.AssociationTypes.Where(a => a.Name == removedAssociate.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.RemoveItem(tmp); } } } storeModelNames = storeModelNames.Distinct().ToList(); var conceptualStoreModels = model.ConceptualModel.EntityTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedStoreModel in conceptualStoreModels) { var tmp = model.ConceptualModel.EntityTypes.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.RemoveItem(tmp); } } var removeConcepEntitySetBase = model.ConceptualModel.Container.BaseEntitySets.Where(a => !storeModelNames.Contains(a.ElementType.Name)).ToList(); foreach (var removedStoreModel in removeConcepEntitySetBase) { var tmp = model.ConceptualModel.Container.BaseEntitySets.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.Container.RemoveEntitySetBase(tmp); } } #endregion #region Mapping if (model.ConceptualToStoreMapping != null && model.ConceptualToStoreMapping.EntitySetMappings != null && model.ConceptualToStoreMapping.EntitySetMappings.Count() > 0) { List<System.Data.Entity.Core.Mapping.EntitySetMapping> lstEntitySetMappings = new List<System.Data.Entity.Core.Mapping.EntitySetMapping>(); bool isMappingExists = false; foreach (var mapping in model.ConceptualToStoreMapping.EntitySetMappings) { isMappingExists = false; if (mapping.EntityTypeMappings != null && mapping.EntityTypeMappings.Count > 0) { foreach (var subMapping in mapping.EntityTypeMappings) { if (subMapping.EntityTypes != null && subMapping.EntityTypes.Count > 0) { foreach (var ef in subMapping.EntityTypes) { if (!storeModelNames.Contains(ef.Name)) { lstEntitySetMappings.Add(mapping); isMappingExists = true; break; } } } if (isMappingExists) break; } } } lstEntitySetMappings = lstEntitySetMappings.Distinct().ToList(); if (lstEntitySetMappings.Count > 0) { foreach (var tmpMapping in lstEntitySetMappings) { var tmp = model.ConceptualToStoreMapping.EntitySetMappings.Where(a => a == tmpMapping).FirstOrDefault(); if (tmp != null) { model.ConceptualToStoreMapping.RemoveSetMapping(tmp); } } } } #endregion } using (var writer = XmlWriter.Create(GetFilePath2(contextType), new System.Xml.XmlWriterSettings { Indent = true })) { EdmxWriter.WriteEdmx(model, writer); } } public string GetFilePath2(Type contextType) { var filename = (contextType.GenericTypeArguments.Length > 0 ? contextType.GenericTypeArguments[0].Name : contextType.FullName) + ".edmx"; string path = Path.Combine(EFFoldPath, filename); return path; } public override DbCompiledModel TryLoad(Type contextType) { string path = GetFilePath2(contextType); if (File.Exists(path)) { DateTime lastWriteTime = File.GetLastWriteTimeUtc(path); DateTime lastWriteTimeDomainAssembly = File.GetLastWriteTimeUtc(contextType.Assembly.Location); if (lastWriteTimeDomainAssembly > lastWriteTime) { File.Delete(path); } } return LoadXml2(contextType, reader => { var defaultSchema = GetDefaultSchema(contextType); return EdmxReader.Read(reader, defaultSchema); }); } internal T LoadXml2<T>(Type contextType, Func<XmlReader, T> xmlReaderDelegate) { var filePath = GetFilePath2(contextType); if (!File.Exists(filePath)) { return default(T); } if (!FileIsValid2(contextType, filePath)) { File.Delete(filePath); return default(T); } using (var reader = XmlReader.Create(filePath)) { return xmlReaderDelegate(reader); } } public bool FileIsValid2(Type contextType, string filePath) { var contextCreated = File.GetLastWriteTimeUtc(contextType.Assembly.Location); var storeCreated = File.GetLastWriteTimeUtc(filePath); return storeCreated >= contextCreated; } } } }

原文链接:C# EF的DbConfiguration加载优化,转载请注明来源!