首页 » 后端 » C# EF的DbConfiguration加载优化

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加载优化,转载请注明来源!