Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(四)
经过上一篇,里面有测试代码,循环60万次,耗时14秒。本次我们增加缓存来优化它。
DbContextExtensions.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using EntityFramework.Extensions;
using System.Linq.Expressions; namespace EntityFrameworkSample
{
public enum AcquiredEdmType
{
TableName, FirstPrimaryKeyNameString, ColumnName
} public struct CachedEdmInfo
{
public EntitySetMapping Mapping { get; set; } public EntitySet TableEntitySet { get; set; } public Dictionary<string, string> PropertyColumnNameDic { get; set; }
} public static class DbContextExtensions
{
private readonly static Dictionary<string, CachedEdmInfo> _mappingCache = new Dictionary<string, CachedEdmInfo>(); #region 基础方法 public static string GetTableName<TEntity>(this DbContext context)
{
return GetTableName(context, typeof(TEntity));
} public static string GetTableName(this DbContext context, Type type)
{
return GetTableNameOrColumnName(context, type, AcquiredEdmType.TableName);
} public static string GetFirstPrimaryKeyName<TEntity>(this DbContext context)
{
return GetFirstPrimaryKeyName(context, typeof(TEntity));
} public static string GetFirstPrimaryKeyName(this DbContext context, Type type)
{
return GetTableNameOrColumnName(context, type, AcquiredEdmType.FirstPrimaryKeyNameString);
} public static string GetColumnName<TEntity, TProperty>(this DbContext context, Expression<Func<TEntity, TProperty>> propertyExpression)
{
return GetTableNameOrColumnName(context, typeof(TEntity), AcquiredEdmType.ColumnName, LambdaHelper.GetPropName(propertyExpression));
} public static string GetColumnName(this DbContext context, Type type, string propertyName)
{
return GetTableNameOrColumnName(context, type, AcquiredEdmType.ColumnName, propertyName);
} private static string GetTableNameOrColumnName(this DbContext context, Type type, AcquiredEdmType edmType, string propertyName = null)
{
if (context == null)
{
throw new ArgumentNullException("dbContext");
}
if (type == null)
{
throw new ArgumentNullException("type");
}
CachedEdmInfo edmInfo;
if (_mappingCache.ContainsKey(type.FullName))
{
edmInfo = _mappingCache[type.FullName];
}
else
{
MetadataWorkspace metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; // Get the part of the model that contains info about the actual CLR types
ObjectItemCollection objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace)); // Get the entity type from the model that maps to the CLR type
EntityType entityType = metadata
.GetItems<EntityType>(DataSpace.OSpace)
.Single(e => objectItemCollection.GetClrType(e) == type); // Get the entity set that uses this entity type
EntitySet entitySet = metadata
.GetItems<EntityContainer>(DataSpace.CSpace)
.Single()
.EntitySets
.Single(s => s.ElementType.Name == entityType.Name); // Find the mapping between conceptual and storage model for this entity set
EntitySetMapping mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single()
.EntitySetMappings
.Single(s => s.EntitySet == entitySet); // Find the storage entity set (table) that the entity is mapped
EntitySet tableEntitySet = mapping
.EntityTypeMappings.Single()
.Fragments.Single()
.StoreEntitySet; edmInfo = new CachedEdmInfo
{
Mapping = mapping,
TableEntitySet = tableEntitySet
};
_mappingCache.Add(type.FullName, edmInfo);
} // Return the table name from the storage entity set
object objTableName = edmInfo.TableEntitySet.MetadataProperties["Table"].Value;
string tableName = objTableName == null ? edmInfo.TableEntitySet.Name : Convert.ToString(objTableName); switch (edmType)
{
case AcquiredEdmType.TableName:
return tableName;
case AcquiredEdmType.FirstPrimaryKeyNameString:
{
var firstKeyProp = edmInfo.TableEntitySet.ElementType.KeyProperties[];
//return tableName + "." + firstKeyProp.Name;
return firstKeyProp.Name;
}
case AcquiredEdmType.ColumnName:
{
// Find the storage property (column) that the property is mapped
edmInfo.PropertyColumnNameDic = edmInfo.PropertyColumnNameDic ?? new Dictionary<string, string>();
if (edmInfo.PropertyColumnNameDic.ContainsKey(propertyName))
{
return edmInfo.PropertyColumnNameDic[propertyName];
}
else
{
string columnName = edmInfo.Mapping
.EntityTypeMappings.Single()
.Fragments.Single()
.PropertyMappings
.OfType<ScalarPropertyMapping>()
.Single(m => m.Property.Name == propertyName)
.Column
.Name;
//写入缓存
edmInfo.PropertyColumnNameDic.Add(propertyName, columnName);
//实际上,下面的 if 判断肯定为 true,但为了避免后期改动了本方法最上面的代码,所以加一个判断。
if (_mappingCache.ContainsKey(type.FullName))
{
_mappingCache[type.FullName] = edmInfo;
}
else
{
_mappingCache.Add(type.FullName, edmInfo);
}
//return tableName + "." + columnName;
return columnName;
}
}
default:
throw new ArgumentNullException("Invalid argument");
}
} #endregion #region 额外方法 #endregion
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using EntityFramework.Extensions;
using System.Linq.Expressions;
using EntityFrameworkSample; namespace EntityFrameworkSample
{
class Program
{
static void Main(string[] args)
{
using (var context = new BloggingContext(@"Data Source=.\SQLExpress;Initial Catalog=TestDB;Persist Security Info=True;User ID=sa;Password=123456"))
{
string blogTableName = context.GetTableName<Blog>();
string postTableName = context.GetTableName<Post>(); Console.WriteLine("Blog maps to: {0}", blogTableName);
Console.WriteLine("Post maps to: {0}", postTableName); string blogPrimaryKeyName = context.GetFirstPrimaryKeyName<Blog>();
string postPrimaryKeyName = context.GetFirstPrimaryKeyName<Post>(); Console.WriteLine("Blog primary key name: {0}", blogPrimaryKeyName);
Console.WriteLine("Post primary key name: {0}", postPrimaryKeyName); System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
for (int i = ; i < ; i++)
{
context.GetColumnName<Blog, string>(c => c.BlogUrl); //经过测试,循环 60 万次,耗时 3.21 秒
}
watch.Stop();
Console.WriteLine("经过测试,循环 60 万次,耗时 {0} 秒", (watch.ElapsedMilliseconds / (double)).ToString("f2")); string blogUrlColumnName = context.GetColumnName<Blog, string>(c => c.BlogUrl);
string postTitleColumnName = context.GetColumnName<Post, string>(c => c.PostTitle); //Console.WriteLine("Blog.BlogUrl maps to: {0}.{1}", blogTableName, blogUrlColumnName);
Console.WriteLine("Post.PostTitle maps to: {0}.{1}", postTableName, postTitleColumnName); }
Console.ReadLine();
} } public class BloggingContext : DbContext
{
public BloggingContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{ } public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new BlogMap());
modelBuilder.Configurations.Add(new PostMap());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
} public class Blog
{
public int Id { get; set; }
public string BlogUrl { get; set; } public List<Post> Posts { get; set; }
} public class Post
{
public int Id { get; set; }
public string PostTitle { get; set; }
public string Body { get; set; } public int BlogId { get; set; }
public Blog Blog { get; set; }
} public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
this.HasKey(c => c.Id);
this.ToTable("t_blog");
this.Property(c => c.Id).HasColumnName("BlogId");
this.Property(c => c.BlogUrl).HasColumnName("Url");
}
} public class PostMap : EntityTypeConfiguration<Post>
{
public PostMap()
{
this.HasKey(c => c.Id);
this.ToTable("t_post");
this.Property(c => c.Id).HasColumnName("PostId");
this.Property(c => c.PostTitle).HasColumnName("Title");
}
}
}
运行截图:

小计:优化后,经过测试,从原来的 循环60万次,耗时14秒,降低到 循环60万次,耗时 3.21 秒。
谢谢浏览!
Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(四)的更多相关文章
- Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(一)
1. 案例1 - 类型和表之间的EF代码优先映射 从EF6.1开始,有一种更简单的方法可以做到这一点.有关 详细信息,请参阅我的新EF6.1类型和表格之间的映射. 直接贴代码了 从EF6.1开始,有一 ...
- Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(五)
直接贴代码了: NewsInfo 实体类: public class NewsInfo { public int NewsInfoId { get; set; } public string News ...
- Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(三)
接着上一篇,我们继续来优化. 直接贴代码了: LambdaHelper.cs using System; using System.Collections.Generic; using System. ...
- Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(二)
接着上一篇 直接贴代码了: using System; using System.Collections.Generic; using System.Data.Entity; using System ...
- 浅析Entity Framework Core中的并发处理
前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core的并发处理方式. 1.常见的并发处 ...
- 在Entity Framework 7中进行数据迁移
(此文章同时发表在本人微信公众号“dotNET每日精华文章”,欢迎右边二维码来关注.) 题记:虽然EF7重新设计了Entity Framework,不过也还是能够支持数据迁移的. Entity Fra ...
- [Programming Entity Framework] 第3章 查询实体数据模型(EDM)(一)
http://www.cnblogs.com/sansi/archive/2012/10/18/2729337.html Programming Entity Framework 第二版翻译索引 你可 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章 ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 4.2. 构建一个搜索查询 搜索数据是几乎所有应用的一个基本功能.它一般是动态的,因 ...
随机推荐
- 这篇文章带你彻底理解synchronized
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- Define the Data Model and Set the Initial Data 定义数据模型并设置初始数据
This topic describes how to define the business model and the business logic for WinForms and ASP.NE ...
- CAD绘图大师都在用的46组快捷键,高效绘图必备
学习CAD 是一个需要慢慢积累的过程,千万不要遇到一点小困难就退缩,有困难我们就一起克服它!今天小编也是来帮助大家克服困难的!很多小伙伴学习CAD已经有一段时间了,但是发现自己的绘图效率还是不高,没关 ...
- 这可能最简单的一种PS图片特效,零基础小白教程
不少小伙伴都想学习PS,可是又觉得PS很难,学了一段时间却还是做不出什么惊艳的效果,没关系!小编今天就来教大家做一个超级简单的图片特效,就算是小白也能轻松学会!我们先来看看图片效果~ 想知道怎么做吗? ...
- JS基础语法---do-while循环 + 总结while循环和do-while循环
1. 总结:while循环和do-while循环 while循环特点:先判断,后循环,有可能一次循环体都不执行 do-while循环特点:先循环,后判断,至少执行一次循环体 对比体会: 1. ...
- 计算机基础 python安装时的常见致命错误 pycharm 思维导图
计算机基础 1.组成 人 功能 主板:骨架 设备扩展 cpu:大脑 计算 逻辑处理 硬盘: 永久储存 电源:心脏 内存: 临时储存,断电无 操作系统(windonws mac linux): 软件,应 ...
- 查看sybase IQ的执行计划
在性能调优工作中,首要的事情是找出性能瓶颈.而针对数据库应用,由于商用数据库对上层应用来说是个黑盒,所以往往需要借助数据库的一些接口或工具来了解数据库的具体行为,并结合相关知识和业务进行调测. ...
- Linux—管理用户、用户组及权限
管理用户 添加用户 [root@localhost ~]# useradd myuser [root@localhost ~]# useradd -m myuser # -d 目录:指定用户主目录,如 ...
- index-css-添加类-移除类-toggleClass-attr
1=>index()会返回当前元素在所有的兄弟元素里面的索引值用法:$("a").click(function(){ console.log($(this).index()) ...
- c# 第32节 类的继承
本节内容: 1:为什么要继承 2:继承特点 3:继承的实现 4:子类传统构造,与base构造 1:为什么要继承 2:继承特点 什么是继承: 继承就是子类包含父类的数据结构和行为方式, 包括字段.属性. ...