Entity Framework
1.EF介绍
- EF是微软以ADO.NET为基础发展的一个ORM框架。
2.ORM
2.1 ORM 介绍
- 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库(如mysql数据库)存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中.
- ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
- 总的来书就是解决了我们写一些重复的,简单的劳动。但是不如原生的会降低性能
3. 认识EF
3.1 EF框架的三种模式
- DataBase First:数据库优先开发方式,先有数据库,然后根据数据库生成实体数据模型。
- Model First:项目开始没有数据库,借助EF设计数据库模型,然后根据模型同步完成数据库及表的创建。简单的来说就是:先有模型再有数据库。
- Code First:代码优先,简单说就是先创建实例类、上下文类,打上特性标签,比如属性不能为空,长度为10等等特性,然后根据类来生成数据库。一般后期修改系统优先使用此方法,这样改动就会非常小。
3.2 EF 关系图解
3.3 EF 文件介绍
- 在使用EF时,系统会帮我们生成一个.edmx文件
- .edmx文件使用XML文件打开,会出现三个块的XML文件
- SSDL content 存储模型内容
- CSDL content 概念模型内容
- C-S mapping content 映射内容
- xx.tt文件是系统使用t4进行生成的,不要随便修改
- xx.content.cs 底下的xx类继承自DbContext类,是我们和数据库交互的类
- xx.cs文件是系统帮我们生成实体类
4.使用EF完成CRUD
4.1 添加数据
-
方式一
-
// 实例化继承自dbCoetent的派生类 SchoolEntities1 db=null; using(db= new SchoolEntities1()) { User user = new User() { Id = 1, userName = "ssr", userPwd = "123456" }; db.User.Add(user); //将数据添加到EF,并将状态标记为添加 db.SaveChanges(); }
-
-
方式二
-
SchoolEntities1 db=null; using(db= new SchoolEntities1()) { User user = new User() { Id = 1, userName = "ssr", userPwd = "123456" }; db.Entry(user).State = System.Data.Entity.EntityState.Added; //标记为添加状态 db.SaveChanges();//保存修改结果 }
-
-
添加多条数据
-
// 实例化继承自dbCoetent的派生类 SchoolEntities1 db = new SchoolEntities1(); for (int i=0;i<7;i++) { User user = new User() { Id = 1+i, userName = "ssr"+i, userPwd = "123456" }; db.User.Add(user); } db.SaveChanges(); /* 当我们调用SaveChanges方法来执行增、删、改时其操作内部都用一个transaction包裹着(自动完成的),不用我们自己去调用事务。*/
-
4.2 查询数据
-
使用Id进行查询
// 实例化继承自dbCoetent的派生类 SchoolEntities1 db = new SchoolEntities1(); var stu1= db.User.Find(1); var stu2= db.User.where(s=>s.id=1).FirstOrDefault();
-
根据条件进行查询
// 实例化继承自dbCoetent的派生类 SchoolEntities1 db = new SchoolEntities1(); // 根据查询条件如果数据返回类型是IQueryable说明是延迟查询 var query= db.User.Where(s=> s.Id>3); //只有在用的时候才进行查询,这就是延迟查询 foreach(var iteam in query) { Console.WriteLine(item); }
-
查询所有
// 实例化继承自dbCoetent的派生类 SchoolEntities1 db = new SchoolEntities1(); var query= db.User.ToList(); foreach(var iteam in query) { Console.WriteLine(item); }
-
分页查询
/*.Skip() 跳过指定的条数 .Take() 获取从指定数据开始的前几条数据 int pageIndex=1;//第几页数据 int pageSize=5;//每页几条数据 .Skip((pageIndex-1)*pageSize).Take(pageSize); */ // 实例化继承自dbCoetent的派生类 SchoolEntities1 db = new SchoolEntities1(); //分页查询一定要排序,pageIndex,pageSize 是做分页的时候,传过来的来参数 var query=db.User.OrderBy(s=>s.id).Skip((pageIndex-1)*pageSize).Take(pageSize)。ToList();
4.3 修改数据
-
方式一
//官方推荐-- 只会修改需要修改的字段 SchoolEntities1 db = new SchoolEntities1(); // 返回的是Student的代理类(包装类) User user=db.User.Where(s=>s.Id==1).FristOrDefault(); //包装类会给真实类修改属性,并且会给他状态设置为已修改状态。 user.Name="sssss"; db.SaveChange();
-
方式二
//会修改全部的字段 SchoolEntities1 db = new SchoolEntities1(); // 返回的是Student的代理类(包装类) User user=db.User.Where(s=>s.Id==1).FristOrDefault(); user.Name="sssss"; db.Entry(user).State = System.Data.Entity.EntityState.Modified; //标记为修改状态 db.SaveChanges();//保存修改结果
4.4 删除数据
-
方式一
SchoolEntities1 db = new SchoolEntities1(); User user =new USer(){Id=1};//也可以从数据库中查询 // User user=db.User.Where(s=>s.id=1).FristOrDefualt(); db.Student.Attach(user); //附加到上下文 db.Student.Remove(user); db.SaveChange();
-
方式二
SchoolEntities1 db = new SchoolEntities1(); User user =new USer(){Id=1};//也可以从数据库 db.Entry(user).State = System.Data.Entity.EntityState.Deleted; //标记为删除状态 db.SaveChanges();//保存修改结果
5.Mode First
5.1 创建Mode
- 打开VS项目添加Ado.Net Model
- 在Vs中建好模型,绑定他们之间的关系,点击新增关系进行邦定就行
- 然后点击更加模型生成数据库即可。
- 然后执行生成的sql语句
- 增删改查跟上面一样
5.2 实例
//两个模型之间的关系为一对多的关系
ModelContainer db = new ModelContainer();
Customer customer = new Customer()
{
CustomerName = "ssr",
CustomerPwd = "123",
SubDateTime = DateTime.Now
};
OrderInfo orderInfo1 = new OrderInfo()
{
Id = Guid.NewGuid(),
OrderNum = "001",
OrderDateTime = DateTime.Now,
Customer = customer
};
db.CustomerSet.Add(customer);
db.OrderInfoSet.Add(orderInfo1);
db.SaveChanges();
6. Code First
6.1 使用CodeFirst
-
创建实体类,并且给实体加上特性标签,并且标注一下实体类之间的关系。
-
在配置文件构建数据库链接字符串。
<add name="connStr" connectionString="server=.;uid=home;pwd=;database=T8" providerName="System.Data.SqlClient"/>
-
创建EF数据操作类
6.2 实例
-
创建两个实体类
public class StudentInfo { //特性标签Key, 标记Id为实例的唯一标识符, 即主键 [Key] public int Id { get; set; } [StringLength(32)] //varchar 必须指定长度, 否则默认长度为max [Required] //不允许为空 public string StuName { get; set; } public DateTime SubTime { get; set; } //CodeFirst中体现两张表的关系 //相当于EF模型中的导航属性 //一个学生 只能对应 一个班级 public virtual ClassInfo ClassInfo { get; set; } } public class ClassInfo { [Key] public int Id { get; set; } [StringLength(32)] [Required] public string ClassName { get; set; } public DateTime CreateTime { get; set; } //CodeFirst中体现两张表的关系 //相当于EF模型中的导航属性 //一个班级 可以对应 多个学生 public virtual ICollection<StudentInfo> StudentInfo { get; set; } }
-
创建和数据库交互的EF上下文类, 继承自DbContext
public class CodeFirstDbContext : DbContext { //1.需要一个构造方法, 调用父类的构造方法, 传入 数据库连接字符串 的名字作为参数 public CodeFirstDbContext() : base("name=connStr") //需配置数据库连接字符串 { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //2.去掉将表名设置为实体类型名称的复数版本 的约定(如 对应ClassInfo 在数据库生成 ClassInfos表) modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } //3. public DbSet<StudentInfo> StudentInfo { get; set; } public DbSet<ClassInfo> ClassInfo { get; set; } }
-
配置数据库连接字符串, 名称与 EF上下文操作类 的构造方法中传入的参数保持一致
<connectionStrings> <add name="connStr" connectionString="server=.;uid=sa;pwd=123456;database=CodeFirstModel" providerName="System.Data.SqlClient" /> </connectionStrings>
-
执行代码, 生成数据库, 并添加一条数据
CodeFirstDbContext db = new CodeFirstDbContext(); db.Database.CreateIfNotExists(); //如果数据库不存在就自动创建 ClassInfo classInfo = new ClassInfo(); classInfo.ClassName = "0302班"; classInfo.CreateTime = DateTime.Now; db.ClassInfo.Add(classInfo); db.SaveChanges();