zoukankan      html  css  js  c++  java
  • 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 来检测生成执行的语句

  • 相关阅读:
    Windows 2003下面Apache+SVN配置
    Oracle中年月日级联填充查询语句
    Tomcat创建一个windows服务
    Oracle10G常用维护语句汇总
    Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
    小谈EasyUI中的tree用法
    正则表达式用法
    执行存储过程返回游标集合转换成List
    面试过程中关于Oracle的查询
    一个可以匹配整数、浮点数的正则表达式
  • 原文地址:https://www.cnblogs.com/cuihongyu3503319/p/8671165.html
Copyright © 2011-2022 走看看