在DbFirst模式中,咱们添加一个EDM(Entity Data Model)后会自动生成一个.edmx文件,这个文件中包含一个继承DbContext类的上下文实例,DbContext是实体类和数据库之间的桥梁,DbContext主要负责与数据交互,主要做用:html
一、DbContext包含全部的实体映射到数据库表的实体集(DbSet < TEntity >)。sql
二、DbContext 将LINQ-to-Entities查询转换为SQL查询并将其发送到数据库。数据库
三、更改跟踪: 它跟踪每一个实体从数据库中查询出来后发生的修改变化。post
四、持久化数据: 它也基于实体状态执行插入、更新和删除操做到数据库中。spa
从上图能够看出:在EF工做过程当中,对实体的操做会致使实体状态的变化,Context根据实体状态的变化生成和执行对应的SQL语句。简言之,对实体的操做给实体添加标签(如Added,Deleted,Modified),DbContext根据实体的标签生成(Insert,Delete,Update)Sql语句,而后EF经过Ado.Net执行Sql实现持久化。.net
DbSet 表示上下文中给定类型的全部实体的集合或可从数据库中查询的给定类型的全部实体的集合。 可使用 DbContext.Set 方法从 DbContext 中建立 DbSet 对象,DbSet对应着数据库中的表,DbSet经常使用的方法以下3d
Add(Entity)/AddRange | 返回添加的Entity | 添加实体到context中,并给实体标记Added状态 dbcontext.Students.Add(studentEntity) |
AsNoTracking<Entity> | DBQuery<Entity> | 获取一个不被context缓冲和追踪的序列,多用于获取只读序列 var studentList = dbcontext.Students.AsNoTracking<Student>().ToList<Student>(); |
Attach(Entity) | 返回添加的Entity | 将实体添加到context上下文中 dbcontext.Students.Attach(studentEntity); |
Find(int) | 返回对应Id的Entity | 经过主键获取实体对象,若是在数据库和context中不存在那么返回null,注:也会返回在context中存在但尚未写入数据库的实体对象。 Student studEntity = dbcontext.Students.Find(1); |
Include | DBQuery | include必须是外键链接,且当即执行;join链接不须要外键 ,延时执行 var studentList = dbcontext.Students.Include("StudentAddress").ToList<Student>(); var studentList = dbcontext.Students.Include(s => s.StudentAddress).ToList<Student>(); |
Remove/RemoveRange | 返回删除的entity | 删除实例,并给实例对象添加deleted标记。 dbcontext.Students.Remove(studentEntity); |
SqlQuery | DBSqlQuery | 经过sql获取实例集合. 默认状况下,返回的集合被追踪的,可使用AsNoTracking()取消追踪。 var studentEntity = dbcontext.Students.SqlQuery("select * from student where studentid = 1").FirstOrDefault<Student>(); |
在EF中实体的五种状态:code
一、detached:实体不在上下文的追踪范围内。如刚new的实例处于detached,能够经过Attach()添加到上下文,此时的状态是unchanged。htm
二、unchanged:未改变,如刚从数据库读出来的实例对象
三、added:添加状态 通常执行 db.Set<T>.Add(t)/ AddRange(ts)时标记为added。由于新对象在数据库中没有相应的记录,全部不能转成deleted和modified状态。
四、deleted:删除状态 通常执行 db.Set<T>.Remove(t)/ RemoveRange(ts)时标记为deleted。数据库中必须先有了相应的记录,全部deleted不能转为added状态。
五、modified:修改状态 改变了实体的属性处于这个状态,能够转为deleted,不能转为added状态。
当EF从数据库中提取一条记录生成一个实体对象以后,应用程序能够针对它的操做太多了,EF是怎么知道哪一个对象处于哪一个状态的?
EF的解决方案是:为当前全部须要跟踪的实体对象,建立一个相应的DbEntityEntry对象,此对象包容着实体对象每一个属性的三个值:Current Value、Original Value和Database Value,只要比较这三个值,很容易地就知道哪一个属性值被修改了(设置:context.Configuration.AutoDetectChangesEnabled = false则不会去追踪,默认是打开的),从而生成相应的Sql命令。对象的状态会随着操做而改变,咱们也能够本身指定状态:
1 //为user生成一个DbEntityEntry对象 2 DbEntityEntry userEntry = context.Entry(user); 3 userEntry.State = EntityState.Added;//添加标记 4 userEntry.State = EntityState.Deleted;//删除标记 5 userEntry.State = EntityState.Modified;//修改标记 6 userEntry.State = EntityState.Unchanged;//无变化标记 7 userEntry.State = EntityState.Detached;//不追踪标记
状态间的转化以下图:
当DbContext执行SaveChanges()方法时,根据实体的状态生成相应的Sql语句,经过Ado.net完成数据的持久化。
EF系列目录连接:Entity Franmework系列教程汇总