【问题标题】:Generating Mapping views from code - EF6从代码生成映射视图 - EF6
【发布时间】:2018-07-05 16:12:55
【问题描述】:

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

我正在尝试在包含 500 多个实体的庞大代码库中实施链接文章中提到的策略,以提高性能。我被以下问题困扰。

发生 System.Data.Entity.Core.EntityCommandCompilationException
HResult=0x8013193B 消息=准备 命令定义。有关详细信息,请参阅内部异常。
来源= StackTrace:

内部异常1:MappingException:当前模型不再 匹配用于预生成映射视图的模型,如所示 由 ViewsForBaseEntitySets3193163ce55837363333438629c877839ae9e7b7494500b6fd275844cda6d343.MappingHashValue 财产。预先生成的映射视图必须使用重新生成 当前模型,如果在运行时生成映射视图,则删除 应改为使用。看 http://go.microsoft.com/fwlink/?LinkId=318050 了解更多信息 实体框架映射视图。

这是我尝试过的。原始文章中关于如何在我可能成为猎物的地方实施它存在一些空白。

第 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() 方法,该方法将在调用时生成视图映射并存储在文件中。

Step2:从 Global.asax 文件 Application_Start() 方法中调用 CheckAndUpdateEFViewCache()。

Step3:在第一次调用上下文的文件中包含程序集。 [组装:DbMappingViewCacheType(typeof(Models.Entities.MyDBContext), typeof(EFDbMappingViewCache))]

我真的不确定这条装配线实际上需要去哪里。链接中没有关于它的信息。 Step3 很有可能是我出错的地方。

有人可以帮助解决这个问题吗?

【问题讨论】:

    标签: c# asp.net performance entity-framework-6


    【解决方案1】:

    我遇到的问题是因为我已经使用 EF 工具生成了一个映射文件并且它已注册。当我编写的配置尝试再注册一次时,EF 抛出了一个错误。

    此外,我想补充一点,缓存数据库模型存储将性能提高了几倍,我最终在我的项目中使用了它。 Link to Cached DB model store usage

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 2014-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多