笔记-ASP .NET MVC EF

https://docs.microsoft.com/zh-cn/ef/ef6/get-started
(微软官方文档)
https://github.com/aspnet/EntityFramework6/
(github的源码)


写在前面的话:关于SQL和LINQ,需看下官方的教程和说明,看官方是如何解释这两个语法,包括一些概念和术语,比如SQL中的select后面应该写的是什么东西 ,LINQ中的from后面写的是什么东西。

1 Entity Framework

EF是基于ADO.NET 数据库访问技术的ORM框架

底层访问呢数据库的实质依然是ADO.NET
ORM框架Object Relational Mapping ,框架包含了实例模型,数据模型,映射关系三部分
上下文类Dbcontext:内部封装了ado.net操作,用于对数据进行crud(增删改查)
子上下文类的属性,其实就是一个集合,可以通过父类的DbSet<>属性获得,利用编写抽象代码

Database First
根据数据库,建立数据库模型的时候,会生成相应代码程序集

Class MyContext:DbContext//MyContext 连接字符串名字的类名
{
public DbSet<UserInfo> UserInfo{get;set;} //数据库中有多少个表就有多少个DbSet<>泛型集合成员
}
public partial class UserInfo
{
public int Uid{get;set;}//根据表里面的字段生成相应的属性
public string UName{get;set}
}
MyContext  myContext = new MyContext();
//查询语法 from in
var list  = from xxx in myContext.UserInfo select xxx;  

//Select
var list = myContext.UserInfo.Select(u=>u);

EF查询 linq

在这里插入图片描述

  • 查询语法 查询语法的顺序和sql语句顺序稍微有点不一样
  • 方法语法

1 基本查询
2 单条件,多条件
3 连接查询**(导航属性)**
4 多from查询(仅查询语法使用,结合导航属性使用)
5 部分列查询:匿名对象
6 分页查询:Skip,Take(仅lambda,一定要县排序后使用此方法)
7 对于一个命令语句,可以将查询语法,方法语法混合使用
8 返回值:IQueryable类型


查询语法

MyContext  myContext = new MyContext();
//DbSet<UserInfo> UserInfo{get;set;}

//建议父类型的变量指向子类型对象,多态,解偶
DbContext dbContext = new MyContext();
//DbSet<TEntity> Set<TEntity>();

dbContext.Set<UserInfo>();
IQueryable<UserInfo> list;

//创建上下文对象
DbContext dbContext = new MyContext();

//基本查询
list = from xxx in dbContext.Set<UserInfo>()
       select xxx;

//单条件查询
list = from xxx in dbContext.Set<UserInfo>()
       where xxx.uid>3
       select xxx;

//多条件查询
list = from xxx in dbContext.Set<UserInfo>()
       where xxx.uid>3 && xxx.name.length >5;
       select xxx;

//查询单列
var list1 = from xxx in dbContext.Set<UserInfo>()
     select xxx.uid;
     
//查询多列 ()
var list1 = from xxx in dbContext.Set<UserInfo>()
     select new xxx_viewmodel//具体对象
     {
     uid = xxx.uid,
     name = xxx.name
     };

var list1 = from cin dbContext.Set<UserInfo>()
     select new //匿名对象
     {
     uid = xxx.uid,
     name = xxx.name
     };

方法语法

MyContext  myContext = new MyContext();
//DbSet<UserInfo> UserInfo{get;set;}

//建议父类型的变量指向子类型对象,多态,解偶
DbContext dbContext = new MyContext();
//DbSet<TEntity> Set<TEntity>();

dbContext.Set<UserInfo>();
IQueryable<UserInfo> list;

//创建上下文对象
DbContext dbContext = new MyContext();

//基本查询
 list = dbContext.Set<UserInfo>();

//单条件查询
 list = dbContext.Set<UserInfo>().Where(u => uid>2);

//多条件查询
list = dbContext.Set<UserInfo>().Where(u => (u.uid > 2)m && (u.name.length < 6));

//当记录中没有数据时,FirstOrDefault不会抛异常,会返回一个Null,First会抛异常
list = dbContext.Set<UserInfo>().Where(u => (u.uid > 2)).Where(u => u.name.length < 6).FirstOrDefault();


list = dbContext.Set<UserInfo>().Where(u => (uid > 2)m || (name.length < 6));


//查询单列
var list = dbContext.Set<UserInfo>().Select(u => u.uid);
     
//查询多列 ()
var list1 =  dbContext.Set<UserInfo>().Select(u => new XXX()
{
uid = u.uid;
name = u.name;
})

//分页查询
list_1 =  dbContext.Set<UserInfo>().OrderByDescending(u=>u.uid).Skip(2).Take(3);   

一对多的表间关系

当在创建数据库的时候,建立外键关系后
EF会自动将表间关系(1对多,1对1,多对多)生成导航属性
在这里插入图片描述

var list = from newsInfo in dbContext.Set<NewsInfo>()
			select new
			{
			info = newsInfo.text;
			type = newsInfo.NewsType.text;//在 NewsInfo类对象中有一个导航属性NewsType,存放着相应的记录对象。
			}

var list = from newsType in dbContext.Set<NewsInfo>()
			select new
			{
			type= newsType.text;
			infos= newsType.NewsInfo.Select(u=>u.text);//在NewsType类对象中有一个导航属性NewsInfo,类型是ICollection<NewsInfo>,存放着相应的记录对象列表。
			}
			

上面的父表和子表都具有导航属性,只是父表的导航属性是ICollection集合,而子表是单类型

//CRUD的两种方式,运用CRUD的方法和状态跟踪,本质都是状态跟踪(没仔细听...)
//增加
dbContext.Set<NewsInfo>().Add(newsInfo);
int result = dbContext.SaveChanges();

//删除
var userinfo =  dbContext.Set<NewsInfo>().Where(u=>u.id = iddelete).FirstOrDefalut();//先查出来
dbContext.Set<UserInfo>().Remove(userinfo );//再删除
int result = dbContext.SaveChanges();
//修改
dbContext.Set<NewsInfo>().AddOrUpdate(userinfo);



//状态追踪修改方式 针对导航属性 
//需要将外键值有效化,不能没有外键值,在对子表进行操作时,需要考虑外键值的有效否,需要引用父表
dbContext.Set<NewsInfo>().Attach(userinfo);
dbContext.Entry(userinfo).State = EntityState.Modified;
dbContext.Entry(userinfo).Property("xxx").IsModified = true;
dbContext.Entry(userinfo).Property("xxx").CurrentValue = userinfo.yyyy;
dbContext.Set<NewsInfo>().AddOrUpdate(userinfo);

EF特性-延迟加载

(这里有个疑问:和ADO的两个查询方式:DataSet和SqlDataReader 有关系吗)
在这里插入图片描述
查询语句返回值如果是IQueryable可以完成延迟加载

//延迟加载:如果不使用数据,则只是拼接sql语句,不会讲结果集加载到内存中来。

DbContext dbContext = new MyContext();
IQueryable<UserInfo>  list1 = dbContext.Set<UserInfo>()//这里默认返回的是IQueryable<T>类型对象
							.OrderByDescending(u=>u.id)//这里的OrderByDescending有多种重载函数,参数写lanmba表达式的,默认将表达式封装成Expression对象,默认是IQueryable<T>的扩展方法(OrderByDescending默认接受,IQueryable<T>类型的this指针)
							.Skip(2)
							.Take(3)
							.Select();//这里的Select有多种重载函数,参数写lanmba表达式的,默认将表达式封装成Expression对象,默认是IQueryable<T>的扩展方法
							

							
IEnumerable<UserInfo>  list2 = dbContext.Set<UserInfo>()
								.AsEnumerable()//这里先将返回值对象强制转换成IEnumerable<T>类型
								.OrderByDescending(u=>u.id)
								.Skip(2)
								.Take()

上述两种方式都只是在拼接sql语句,

但是IQueryable可以拼接完整的sql语句,每次使用List时,会向数据库执行完整的sql语句;(推荐使用IQueryable查询)
IEnumerable不能拼接完整sql语句,每次使用List时,它只是将第一个sql语句去数据库执行,其他都sql语句在内存中操作

IQueryable和IEnumerable的差异是:IQueryable继承IEnumerable,并且多了个Expression类型的属性,可以拼接树形命令。

集合类型的导航属性也采用延迟加载,,即导航属性在使用的时候,才回去执行sql语句去执行(这一点说起来感觉有点奇怪,感觉这句话有点多余,可能有什么点我没有Get到),可能在正常查询子表时,会自动查询父表的信息。

上面都是延迟加载,那如何禁止延迟加载呢?

  • 如果查询结果是个集合,在查询语句的结尾调用**ToList()**方法
  • 如果查询结果是个单值,在查询语句的结尾调用**FirstOrDefault()**方法
  • 对于导航属性,可以在查询结果上使用**Include()**方法
IQueryable<UserInfo>  list1 = dbContext.Set<UserInfo>().OrderByDescending(u=>u.id).Skip(2).Take(3).ToList();

IQueryable<UserInfo>  list1 = dbContext.Set<UserInf().OrderByDescending(u=>u.id).Skip(2).Take(3).Include(n=>n.NewsType).ToList();
//导航属性的非延迟加载				

延迟加载的优缺点

  • 优点:用的时候才请求数据库获取数据,可以实时获取数据,适用于数据变化大的情况;
  • 缺点:每次用数据时就会发生一次数据库请求,增加了数据库的压力,若数据没有变化性小的情况,延迟加载就不适用了;

总结:

EF实现curd

  • 两种查询方式:查询语法和方法语法
  • 增加,修改,删 有两种操作:方法版和状态版,本质都是状态版
  • 导航属性:当两个边之间有外键关系时,在生产程序集时,会生产相关的导航属性,根据映射关系的不同,导航属性的类型不同,有集合类型和单值类型
  • 延迟加载:IQueryable,IEnumerable ,导航属性默认延迟加载;同时可以禁止延迟加载

相关链接

https://www.cnblogs.com/wujingtao/p/5401113.html
http://www.cnblogs.com/VolcanoCloud/p/4517310.html


2 基本sql语句

1 sql 语句字符串用单引号
2 sql语句对大小写不敏感 (字段名,关键词,表名)
3 表名建议加前缀

insert into t_student(name,age) values('jay',19);--插入一条记录 

select id,name,age from t_student;--表的选中字段列
select * from t_student;--表的所有字段列
select * from t_student where uid = "123";

delete from t_student where name = 'JAY';--删除name字段为JAY的记录
delete from t_student where age > 11 or height >170;--删除name字段为JAY的记录
delete from t_student where age > 11 and height >170;--删除name字段为JAY的记录
delete from t_student;--删除所有记录

update t_student set age = age+1;
update t_student set height = 100;
update t_student set height = 100,age = age+1;
update t_student where height < 170 set age =11;
update t_student where uid = '123' set age =11;

select name as name1,age as age1 from t_student;--查询结果看到的字段名为name1和age1,但数据库字段名并没有改动
select name,1 from t_student; --将t_student表里面的name字段列全为1
select GETDATE() as updatetime from t_student;--sql语句内置的函数


--数据汇总
select MAX(age) from t_student;--利用sql语句内置函数获取年龄的最大值单独成一列
select MAX(age) from t_student;
select MAX(age),MIN(age)AVG(age)COUNT(*) from t_student;--利用sql语句内置函数获取年龄的最大值,最小值,平均值,总数量呈四列
select COUNT(*) from t_student where Age > 100;
select COUNT(*) from t_student where Age > 100 && Height < 180;

//通配符
select * from t_student where Name like 'y%';--模拟搜索开头为y的字符,
select * from t_student where Name like 'y%k';--模拟搜索y开头k结尾字符
select * from t_student where Name like '%k%';--模拟搜索含有k字符
--like查询会很耗时间,一般在大型项目中慎用,一般用全文检索方式代替

--数据排序
select *from t_student order by Age;--按照年龄排序,order从小到大
select *from t_student order by Age Desc;--降序 
select *from t_student order by Age,Height;--先Age升序 ,后Height升序
select *from t_student order by Age,Height Desc;--先Age升序 ,后Height降序 

//先where过滤数据,在用order by排序

3 EF-edmx

1在这里插入图片描述


2
在这里插入图片描述


3
在这里插入图片描述


4
在这里插入图片描述


5
在这里插入图片描述


6

在这里插入图片描述


7
在这里插入图片描述


4 EF-model first

1
在这里插入图片描述


2
在这里插入图片描述


3
在这里插入图片描述


4
在这里插入图片描述


5

在这里插入图片描述


6

在这里插入图片描述


7
在这里插入图片描述


8
在这里插入图片描述


9
在这里插入图片描述


10
在这里插入图片描述


11
在这里插入图片描述


12

在这里插入图片描述


5 EF-code first

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述


运行后,数据库中就有相应的表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值