EntityFramework 常见用法汇总
1、Code First 启用存储过程映射实体
- 1 protected override void OnModelCreating(DbModelBuilder modelBuilder)
- 2 {
- 3 base.OnModelCreating(modelBuilder);
- 4 modelBuilder.Entity<Destination>().MapToStoredProcedures();
- 5 }
2、接管自己的Transaction,实现高度自定义
- 1 DbContext db = new DbContext();
- 2 db.Database.BeginTransaction();
3、三种实体加载模式EagerLoad(预加载),LazyLoad(延迟加载),ExplicitLoading(手动加载)

- 1 DbContext db = new DbContext();
- 2 db.Table1.Include(d=>d.Table2);//预加载
- 3
- 4 public class EntityTable
- 5 {
- 6 public virtual EntityTable2 ForeignKeyTable { get; set; } //使用virtual实现延迟加载
- 7 }
- 8
- 9 dbContext.Entry(YouSelectModel).Collection(t => t.References).Load();//显式手动加载

4、Code First自定义存储过程调用

- 1 public virtual int sp_test_delete(Nullable<int> id)
- 2 {
- 3 var idParameter = id.HasValue ?
- 4 new ObjectParameter("id", id) :
- 5 new ObjectParameter("id", typeof(int));
- 6
- 7 return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_test_delete", idParameter);
- 8 }

5、DbContext对象追踪
- 1 DbContext db = new DbContext();
- 2 db.ChangeTracker.Entries(); //获取所有的实体
- 3 db.Table1.Local;//获取某张表下状态为修改或者增加的状态,注意不能追踪删除状态的实体
- 4 db.Table1.AsNoTracking().ToList();//这样查询出来的数据,DbContext将不会追踪,修改后,SaveChanges不会更新到数据库
6、Entity Framework的仓储模式提供的Find方法
- 1 DbContext db = new DbContext();
- 2 db.Table1.Find(20);//这个方法是仓储模式提供的,没有用到IQuerable提供的扩展方法,不会
7、重写ShouldValidateEntity和ValidateEntity实现Entity Framework自定义模型验证

- 1 protected override bool ShouldValidateEntity(DbEntityEntry entityEntry)//返回实体是否需要验证
- 2 {
- 3 return base.ShouldValidateEntity(entityEntry);
- 4 }
- 5 protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)//实体的自定义验证方法,此为验证学生实体姓名不能为abc
- 6 {
- 7 List<DbValidationError> error = new List<DbValidationError>();
- 8 if (entityEntry.Entity is Student)
- 9 {
- 10 if ((entityEntry.Entity as Student).Name == "abc")
- 11 {
- 12 error.Add(new DbValidationError("Name", "不能为abc"));
- 13 }
- 14 }
- 15 if (error.Count > 0)
- 16 {
- 17 return new DbEntityValidationResult(entityEntry, error);
- 18 }
- 19 else
- 20 {
- 21 return base.ValidateEntity(entityEntry, items);
- 22 }
- 23 }

8、实现Interception来截获EF底层执行的SQL语句,也可以使用这个拦截器实现读写分离

- 1 /// <summary>
- 2 /// SQL命令拦截器
- 3 /// </summary>
- 4 public class NoLockInterceptor : IDbCommandInterceptor
- 5 {
- 6 public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
- 7 {
- 8 throw new NotImplementedException();
- 9 }
- 10
- 11 public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
- 12 {
- 13 throw new NotImplementedException();
- 14 }
- 15
- 16 public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
- 17 {
- 18 throw new NotImplementedException();
- 19 }
- 20
- 21 public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
- 22 {
- 23 throw new NotImplementedException();
- 24 }
- 25
- 26 public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
- 27 {
- 28
- 29 }
- 30
- 31 public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
- 32 {
- 33
- 34 }
- 35 }

然后在程序启动时执行以下代码来实现监控
- System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new NoLockInterceptor());
或者在配置文件中增加interceptors节点,下面增加interceptor

- 1 <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
- 2 <interceptors>
- 3 <interceptor type="ConsoleApp2.abc.NoLockInterceptor,ConsoleApp2"></interceptor>//格式是全部命名空间加类名,然后逗号,命名空间的首个节点,这里我也没明白为什么这么写,C#好多配置文件都这么配置的
- 4 </interceptors>
- 5 <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
- 6 <providers>
- 7 <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
- 8 </providers>
- 9 </entityFramework>

9、code first 的 3种对象关系,one to one 、one to multi、 multi to multi
one to one 1对1,1个学生对应1个学生地址,1个学生地址对应1个学生,可能1个学生下没有学生地址

- 1 public class Student
- 2 {
- 3 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- 4 public int ID { get; set; } 7 public virtual StudentAddress StudentAddress{ get; set; } //关键
- 8 }
- 9 public class StudentAddress
- 10 {
- 11 [Key,ForeignKey("Student")] //关键
- 12 public int ID { get; set; }14 public virtual Student Student{ get; set; }
- 15 }

one to multi 一对多,一个学生地址下可能有多个学生,1个学生只能有一个学生地址

- 1 public class Student
- 2 {
- 3 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- 4 public int ID { get; set; }
- 5 public virtual StudentAddress StudentAddress { get; set; } //关键
- 6
- 7 }
- 8
- 9 public class StudentAddress
- 10 {
- 11 [Key] //注意这里
- 12 public int ID { get; set; }
- 13
- 14 public virtual ICollection<Student> Destination { get; set; } //关键
- 15 }

multi to multi 多对多,1个学生下可能有多个地址,1个地址也可能有多个学生

- 1 public class Student
- 2 {
- 3 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- 4 public int ID { get; set; }
- 5 public virtual ICollection<StudentAddress> StudentAddress { get; set; } //关键
- 6
- 7 }
- 8
- 9 public class StudentAddress
- 10 {
- 11 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] //注意这里有不一样的地方
- 12 public int ID { get; set; }
- 13
- 14 public virtual ICollection<Student> Destination { get; set; } //关键
- 15 }

10、使用DataAnnotations来修改默认协定
Key 主键
Timestamp 设置并发时间戳
ConcurrencyCheck 设置当前字段参与开放式并发校验
Required 设置字段非空
MaxLength 设置字符串的最大长度
MinLength 设置字符串的最小长度
Table 设置实体对应数据库表的名称
Column 设置字段对应数据库表字段的名称
ForeignKey 设置外检
NotMapped 这个字段不生成在数据库表中,不用于生成sql
11、Fluent api配置

- 1 protected override void OnModelCreating(DbModelBuilder modelBuilder)
- 2 {
- 3 var studentConfig = modelBuilder.Entity<Student>();
- 4 studentConfig.ToTable("StudentDetail");//修改当前实体对应的表名
- 5 studentConfig.Map<Student>(d=> //Map自定义表的schame,常用于将一个实体生成两个表
- 6 {
- 7 d.Properties(p=>new { p.StudentId,p.StudentName });//设置当前实体需要映射表字段的列
- 8 d.ToTable("StudentDetail"); //设置当前表对应数据库的名称
- 9 }).Map(Student>(d=>
- 10 {
- 11 d.Properties(p=>new { p.StudentId,p.Address });//设置当前实体需要映射表字段的列
- 12 d.ToTable("StudentDetail2"); //设置当前表对应数据库的名称
- 13 });
- 14 studentConfig.Property(d=>d.StudentName).HasColumnName("NewTable").HasMaxLength(100).IsRequired();//给字段设置名字和最大长度和必填
- 15 }

这样,一个表的Fluent Api可能有很多,一个数据库如果几百张表那么可能会有很多这个设置的代码,全部在DbContext忠会很多
可以这样分离

- 1 public class StudentConfiguration : EntityTypeConfiguration<Student>
- 2 {
- 3 public StudentConfiguration()
- 4 {
- 5 this.ToTable("NewTable");
- 6 }
- 7 }
- 8 //这样可以把Fluent Api分离到多个文件中
- 9 //然后在DbContext中的OnModelCreating中增加
- 10 modelBuilder.Configurations.Add(new StudentConfiguration());

12、Code First的初始化策略 IfNotExists,IfModelChanges,Always,Custom
- 1 Database.SetInitializer<SchoolDBEntity>(new CreateDatabaseIfNotExists<SchoolDBEntity>()); //创建数据库,如果数据库未存在
- 2 Database.SetInitializer<SchoolDBEntity>(new DropCreateDatabaseIfModelChanges<SchoolDBEntity>()); //删除数据库后重新创建
- 3 Database.SetInitializer<SchoolDBEntity>(new DropCreateDatabaseAlways<SchoolDBEntity>());//每次运行程序都会删除数据库重新创建
- 4 Database.SetInitializer<SchoolDBEntity>(new NullDatabaseInitializer<SchoolDBEntity>()); //禁用数据库初始化策略
使用中自定义的初始化器,但是基本上也是只能在创建完毕后,加入初始化数据

- 1 public class MyCreateDatabaseIfNotExists: CreateDatabaseIfNotExists<BreakAwayContext>
- 2 {
- 3 public override void InitializeDatabase(BreakAwayContext context)
- 4 {
- 5 base.InitializeDatabase(context);
- 6 }
- 7 protected override void Seed(BreakAwayContext context)
- 8 {
- 9 Console.WriteLine("数据库创建完毕,可以创建初始化数据");
- 10 base.Seed(context);
- 11 }
- 12 }

13、使用Migration进行无缝迁移
1、启用Migration
enable-migrations
2、项目启动时运行以下代码,来实现自动迁移
- 1 Database.SetInitializer(new MigrateDatabaseToLatestVersion<BreakAwayContext, Migrations.Configuration>());
3、如果不使用自动迁移则使用 update-database来修改数据库
14、使用Entity Framework Profiler监控EF生成的语句
1、安装EfProf
2、引入HibernatingRhinos.Profiler.Appender
后在代码中执行以下语句,来截获EF的各种sql
HibernatingRhinos.Profiles.Appender.EntityFramework.EntityFrameworkProfiler.Initialze();
3、打开EfProf 来检测生成执行的语句
EntityFramework 常见用法汇总的更多相关文章
- curl命令常见用法汇总 good
curl是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在"标准输出"(stdout)上面. curl是一个强大的命令行工具,它可以通过网络将信息传递给服务器或者从服 ...
- pip常见用法汇总
1.pip安装 yum -y install epel-release && yum -y install python-pip 2.pip安装软件 (1)安装单个软件:pip ins ...
- Linux中find常见用法
Linux中find常见用法示例 ·find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数 ...
- php中的curl使用入门教程和常见用法实例
摘要: [目录] php中的curl使用入门教程和常见用法实例 一.curl的优势 二.curl的简单使用步骤 三.错误处理 四.获取curl请求的具体信息 五.使用curl发送post请求 六.文件 ...
- Guava中Predicate的常见用法
Guava中Predicate的常见用法 1. Predicate基本用法 guava提供了许多利用Functions和Predicates来操作Collections的工具,一般在 Iterabl ...
- find常见用法
Linux中find常见用法示例 ·find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数 ...
- iOS 开发多线程篇—GCD的常见用法
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- iOS开发多线程篇—GCD的常见用法
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- [转]EasyUI——常见用法总结
原文链接: EasyUI——常见用法总结 1. 使用 data-options 来初始化属性. data-options是jQuery Easyui 最近两个版本才加上的一个特殊属性.通过这个属性,我 ...
随机推荐
- 现代前端技术解析:Web前端技术基础
最近几年,越来越多的人投入到前端大军中:时至至今,前端工程师的数量仍然不能满足企业的发展需求:与此同时,互联网应用场景的复杂化提高了对前端工程师能力的要求,一部分初期前端工程师并不能胜任企业的工作 ...
- [置顶]
Deep Learning 资料库
一.文章来由 网络好文章太多,而通过转载文章做资料库太麻烦,直接更新这个博文. 二.汇总 1.台大李宏毅老师的课 正片:http://speech.ee.ntu.edu.tw/~tlkagk/cour ...
- D. Closest Equals(线段树)
题目链接: D. Closest Equals time limit per test 3 seconds memory limit per test 256 megabytes input stan ...
- 【商业源码】生日大放送-Newlife商业源码分享 -转
http://www.cnblogs.com/asxinyu/p/3225179.html 今天是农历六月二十三,是@大石头的生日,记得每年生日都会有很劲爆的重量级源码送出,今天Newlife群和 ...
- vuex(一)mutations
前言:vuex的使用,想必大家也都知道,类似于状态库的东西,存储某种状态,共互不相干的两个组件之间数据的共享传递等.我会分开给大家讲解vuex的使用,了解并掌握vuex的核心(state,mutati ...
- 【剑指offer】连续子数组的最大和,C++实现
原创博文,转载请注明出处!本题牛客网地址 博客文章索引地址 博客文章中代码的github地址 # 题目 输入一个整形数组,数组里有正数也有负数.数组中的一个或连续多个整数组成一个子数组.求 ...
- 掌握Git撤销操作,随心所欲控制文件状态
本文主要讨论和撤销有关的 git 操作.目的是让读者在遇到关于撤销问题时能够方便迅速对照执行解决问题,而不用去翻阅参数繁多的 git 使用说明. 一开始你只需了解大致功能即可,不必记住所有命令和具体参 ...
- 一步步搭建自己的web服务器
IIS或者其他Web服务器究竟做了哪些工作,让浏览器请求一个URL地址后显示一个漂亮的网页?要想弄清这个疑问,我想我们可以自己写一个简单的web服务器. 思路: 创建socket监听浏览器请求. 连接 ...
- c语言输出4*5的数列?
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 输出上面的数列,用c实现的代码:<pre lang="c" line=&quo ...
- 每天一个linux命令:【转载】cat命令
cat命令的用途是连接文件或标准输入并打印.这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用. 1.命令格式: cat [选项] [文件] ...