博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EntityFramework 常见用法汇总
阅读量:5937 次
发布时间:2019-06-19

本文共 7538 字,大约阅读时间需要 25 分钟。

1、Code First 启用存储过程映射实体 

1 protected override void OnModelCreating(DbModelBuilder modelBuilder)2 { 3 base.OnModelCreating(modelBuilder); 4 modelBuilder.Entity
().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
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
items)//实体的自定义验证方法,此为验证学生实体姓名不能为abc 6 { 7 List
error = new List
(); 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         ///  2         /// SQL命令拦截器 3 ///  4 public class NoLockInterceptor : IDbCommandInterceptor 5 { 6 public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext
interceptionContext) 7 { 8 throw new NotImplementedException(); 9 } 10 11 public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) 12 { 13 throw new NotImplementedException(); 14 } 15 16 public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) 17 { 18 throw new NotImplementedException(); 19 } 20 21 public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) 22 { 23 throw new NotImplementedException(); 24 } 25 26 public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext
interceptionContext) 27 { 28 29 } 30 31 public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext
interceptionContext) 32 { 33 34 } 35 }

  然后在程序启动时执行以下代码来实现监控

System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new NoLockInterceptor());

  或者在配置文件中增加interceptors节点,下面增加interceptor

1   
2
3
//格式是全部命名空间加类名,然后逗号,命名空间的首个节点,这里我也没明白为什么这么写,C#好多配置文件都这么配置的 4
5
6
7
8
9

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
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 { 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
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
(); 4 studentConfig.ToTable("StudentDetail");//修改当前实体对应的表名 5 studentConfig.Map
(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
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
(new CreateDatabaseIfNotExists
()); //创建数据库,如果数据库未存在2 Database.SetInitializer
(new DropCreateDatabaseIfModelChanges
()); //删除数据库后重新创建 3 Database.SetInitializer
(new DropCreateDatabaseAlways
());//每次运行程序都会删除数据库重新创建 4 Database.SetInitializer
(new NullDatabaseInitializer
()); //禁用数据库初始化策略

  使用中自定义的初始化器,但是基本上也是只能在创建完毕后,加入初始化数据

1 public class MyCreateDatabaseIfNotExists: CreateDatabaseIfNotExists
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
());

  3、如果不使用自动迁移则使用 update-database来修改数据库

14、使用Entity Framework Profiler监控EF生成的语句

  1、安装EfProf

  2、引入HibernatingRhinos.Profiler.Appender

    后在代码中执行以下语句,来截获EF的各种sql

    HibernatingRhinos.Profiles.Appender.EntityFramework.EntityFrameworkProfiler.Initialze();

  3、打开EfProf 来检测生成执行的语句

转载地址:http://otvtx.baihongyu.com/

你可能感兴趣的文章
layer弹出信息框API
查看>>
delete from inner join
查看>>
WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍...
查看>>
git merge 和 git merge --no-ff
查看>>
kernel笔记——内核编译与进程管理
查看>>
shell中定义变量用双引号和单引号以及不用引号的区别
查看>>
去除ArcMap连接空间数据库中多余的属性表
查看>>
独立软件开发商进军SaaS注意八个问题,互联网营销
查看>>
kvc
查看>>
jdk内存的分配
查看>>
关于self.用法的一些总结
查看>>
UIView翻译 (参考)
查看>>
Android Display buffer_handle_t的定义
查看>>
SSH详解
查看>>
ASM概述
查看>>
【290】Python 函数
查看>>
godaddy域名转发(域名跳转)设置教程
查看>>
silverlight学习布局之:布局stackpanel
查看>>
理解并自定义HttpHandler
查看>>
Linux各发行版流行度统计数据与排名
查看>>