经过上一篇,里面有测试代码,循环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 信息?(四)的更多相关文章

  1. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(一)

    1. 案例1 - 类型和表之间的EF代码优先映射 从EF6.1开始,有一种更简单的方法可以做到这一点.有关 详细信息,请参阅我的新EF6.1类型和表格之间的映射. 直接贴代码了 从EF6.1开始,有一 ...

  2. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(五)

    直接贴代码了: NewsInfo 实体类: public class NewsInfo { public int NewsInfoId { get; set; } public string News ...

  3. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(三)

    接着上一篇,我们继续来优化. 直接贴代码了: LambdaHelper.cs using System; using System.Collections.Generic; using System. ...

  4. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(二)

    接着上一篇 直接贴代码了: using System; using System.Collections.Generic; using System.Data.Entity; using System ...

  5. 浅析Entity Framework Core中的并发处理

    前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core的并发处理方式. 1.常见的并发处 ...

  6. 在Entity Framework 7中进行数据迁移

    (此文章同时发表在本人微信公众号“dotNET每日精华文章”,欢迎右边二维码来关注.) 题记:虽然EF7重新设计了Entity Framework,不过也还是能够支持数据迁移的. Entity Fra ...

  7. [Programming Entity Framework] 第3章 查询实体数据模型(EDM)(一)

    http://www.cnblogs.com/sansi/archive/2012/10/18/2729337.html Programming Entity Framework 第二版翻译索引 你可 ...

  8. 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章  ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 4.2. 构建一个搜索查询 搜索数据是几乎所有应用的一个基本功能.它一般是动态的,因 ...

随机推荐

  1. jxl解析excel时,处理中文乱码问题

    jxl解析excel时,处理中文乱码问题 一般出现较多的问题是,当exce中包含了中文或特殊字符时,在解析时候就会出现乱码现象. 解决方法为: InputStream in = new FileInp ...

  2. git clone和git pull的区别

    1.需不需要本地文件夹是仓库 git clone是将整个工程复制下来所以,不需要本地是仓库(没有.git文件夹)   git clone git pull需要先初始化本地文件夹文一个仓库   git ...

  3. maven新建项目的几种方式和启动

    方式一: 第1步:转到 New 菜单 Other.. -> Maven -> Maven Project ,然后单击 Next .如下图所示 - 第2步:在New Maven Projec ...

  4. ts常用数据类型

    1.1 布尔值 let isTrue: boolean = false; console.log(isTrue); 1.2 数字 let age: number = 26; console.log(a ...

  5. phpstorm xdebug 无法断点调试问题

    最近用phpstorm+xdebug调试一段php代码的时候莫名其妙的无法切入断点调试 本地用的php集成环境是UPUPW ANK V1.1.7 64Bit 选择了集成环境中php版本为7.1.x 搞 ...

  6. 用Toad for Oracle创建数据库表空间和用户

    打开Toad, 1,菜单栏Session—>new Connection….打开如下窗口: 2,进入之后,菜单DatebaseàSechema  Brower...找到Table Space(表 ...

  7. mssql 单引号插入到sqlserver的方法分享

    转自:http://www.maomao365.com/?p=6740 摘要: 下文讲述sqlserver操作中遇到单引号的处理方法sqlserver 数据库中可以存储任何字符,因为在数据库中字符都是 ...

  8. linux 添加用户并设置主目录,shell 并赋予权限 (以 fedora 和 ubuntu 为例)

    环境 centos 7.6 添加用户: [root@localhost ~]# useradd -d /home/yaoxu -m -s /bin/bash yaoxu 更改用户密码: passwd ...

  9. MIPI CSI2学习(一):说一说MIPI CSI2

    1. MIPI CSI2简介 MIPI联盟是一个开放的会员制组织.2003年7月,由美国德州仪器(TI).意法半导体(ST).英国ARM和芬兰诺基亚(Nokia)4家公司共同成立.MIPI联盟旨在推进 ...

  10. JEB动态调试解密数据包加密字段

    0x00 场景 在测试某个app的时候,抓取数据包,发现某些参数存在被加密的情况,或者有签名校验的情况,这个时候如果我们想直接去篡改数据包的内容往往是做不到的,那就来看看抓取的某个app登录数据包,如 ...