Создание картографических представлений из кода - EF6 - PullRequest
0 голосов
/ 05 июля 2018

https://msdn.microsoft.com/en-us/data/dn469601.aspx

Я пытаюсь реализовать стратегию, упомянутую в связанной статье, в моей огромной базе кода с более чем 500 объектами для повышения производительности. Я застрял со следующей проблемой.

Произошло исключение System.Data.Entity.Core.EntityCommandCompilationException
HResult = 0x8013193B Сообщение = Произошла ошибка при подготовке определение команды. Подробности смотрите во внутреннем исключении.
Source = StackTrace:

Внутреннее исключение 1: MappingException: текущая модель больше не соответствует модели, использованной для предварительной генерации отображений, как указано посредством ViewsForBaseEntitySets3193163ce55837363333438629c877839ae9e7b7494500b6fd275844cda6d343.MappingHashValue имущество. Предварительно сгенерированные представления карт должны быть либо восстановлены с использованием текущая модель или удалена, если отображаемые представления генерируются во время выполнения следует использовать вместо Увидеть http://go.microsoft.com/fwlink/?LinkId=318050 для получения дополнительной информации о Представления отображения Entity Framework.

Вот что я пробовал. В оригинальной статье есть несколько пробелов относительно того, как это должно быть реализовано там, где я мог бы стать жертвой.

Шаг 1: Я создал класс, который расширяет DBMappingViewCache.

public class EFDbMappingViewCache : DbMappingViewCache
    {
        protected static string _mappingHashValue = String.Empty;
        public override string MappingHashValue
        {
            get
            {
                return GetCachedHashValue();
            }
        }

        public override DbMappingView GetView(EntitySetBase extent)
        {
            Dictionary<string, string> dict = GetMappedViewFromCache();
            if (extent == null)
            {
                throw new ArgumentNullException("extent");
            }
            if(dict.ContainsKey(extent.Name))
            {
                return new DbMappingView(dict[extent.Name]);
            }
            return null;
        }


        public static string GetCachedHashValue()
        {
            string cachedHash;
            string path = HttpContext.Current.Server.MapPath(@"~\EFCache\MappingHashValue.txt");
            if (!File.Exists(path))
            {
                File.Create(path).Dispose();
            }
            using (var streamReader = new StreamReader(path, Encoding.UTF8))
            {
                cachedHash = streamReader.ReadToEnd();
            }
            return cachedHash;
        }

        public static void UpdateHashInCache(string hashValue)
        {
            string path = HttpContext.Current.Server.MapPath(@"~\EFCache\MappingHashValue.txt");
            using (var streamWriter = new StreamWriter(path, false))
            {
                streamWriter.Write(hashValue);
            }
        }

        private static void UpdateMappedViewInCache(Dictionary<EntitySetBase, DbMappingView> dict)
        {
            string path = HttpContext.Current.Server.MapPath(@"~\EFCache\MappingView.json");
            Dictionary<String, String> stringDict = new Dictionary<string, string>();
            foreach(var entry in dict)
            {

                stringDict[entry.Key.Name] = entry.Value.EntitySql.ToString();                
            }
            var json = new JavaScriptSerializer().Serialize(stringDict);
            using (var streamWriter = new StreamWriter(path, false))
            {
                streamWriter.Write(json);
            }
        }

        private static Dictionary<String, string> GetMappedViewFromCache()
        {
            string path = HttpContext.Current.Server.MapPath(@"~\EFCache\MappingView.json");
            var json = String.Empty; 
            using (var streamReader = new StreamReader(path, Encoding.UTF8))
            {
                json = streamReader.ReadToEnd();
            }
            Dictionary<String, string> mappedViewDict = new Dictionary<String, string>();
            if (!String.IsNullOrEmpty(json))
            {
                var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
                mappedViewDict = ser.Deserialize<Dictionary<String, string>>(json);
            }
            return mappedViewDict;
        }

        public static void CheckAndUpdateEFViewCache()
        {
            using (var ctx = new CascadeTranscationsDbContext(DBHelper.GetConnString()))
            {

                var objectContext = ((IObjectContextAdapter)ctx).ObjectContext;
                var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace
                                                                                    .GetItemCollection(DataSpace.CSSpace);
                string computedHashValue = mappingCollection.ComputeMappingHashValue();
                string currentHashValue = GetCachedHashValue();
                SetHashValue(computedHashValue);
                if (computedHashValue != currentHashValue)
                {
                    UpdateHashInCache(computedHashValue);
                    IList<EdmSchemaError> errors = new List<EdmSchemaError>();
                    Dictionary<EntitySetBase, DbMappingView> result = mappingCollection.GenerateViews(errors);
                    UpdateMappedViewInCache(result);
                }
            }
        }


    }

Я сохранил хеш-значение и сопоставление, сгенерированные в файле, и извлек их в методе GetView ().

Я выставил открытый метод CheckAndUpdateEFViewCache (), который будет генерировать отображение представления при вызове и сохранять в файле.

Шаг 2: вызов метода CheckAndUpdateEFViewCache () из файла Global.asax метода Application_Start ().

Шаг 3: Включить сборку в файл, где контекст сначала вызывается. [сборка: DbMappingViewCacheType (typeof (Models.Entities.MyDBContext), typeof (EFDbMappingViewCache))]

Я действительно не уверен, куда на самом деле должна идти эта сборочная линия. Информации об этом в ссылке нет. Есть действительно хороший шанс, что Step3 может быть там, где я ошибся.

Может кто-нибудь помочь с проблемой?

1 Ответ

0 голосов
/ 11 июля 2018

Проблема, с которой я столкнулся, заключалась в том, что у меня уже был сопоставленный файл, созданный с помощью EF Tools, и он был зарегистрирован. Когда конфигурация, которую я написал, попыталась зарегистрироваться еще раз, EF выдал ошибку.

Далее я хочу добавить, что хранилище моделей Cached DB улучшило производительность в несколько раз, и в итоге я использовал именно это в своем проекте. Ссылка на использование хранилища моделей кэшированных БД

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...