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();
|