EF框架知识点梳理

(一)LINQ

(Language Integrated Query)语言集成查询
可以使用统一的方式(相同的查询语法)来查询和转换XML、对象集合、SQL数据库、ADO.NET数据集以及任何其他可用的LINQ提供程序格式的数据。从而消除编程语言和数据库之间的不匹配。
一般步骤:获取数据源、创建查询、执行查询。注:尽管查询在语句中定义,但直到最后的foreach语句请求其结果的时候才会执行

LINQ主要包含以下三部分:
1、LINQ to Objects 主要负责对象的查询
2、LINQ to XML 主要负责XML的查询。
3、LINQ to ADO.NET(SQL/DataSet/Entities)主要负责数据库的查询

使用LINQ写查询时可以使用两种形式的语法:查询语法和方法语法
方法语法(method syntax): 使用标准的方法调用,这些方法是一组叫做标准查询运算符的方法   
查询语法(query method) : 看上去和SQL语句相似,使用查询表达式形式书写。微软推荐使用查询语法,因为更易读

1.查询语法(Query Expression)

必须以from子句开头,以select/group子句结束

  • 1)from…in子句:指定查询数据源
    例:from Type Item in Items //Type是元素类型,可省略
  • 2)join…in…on…equals…子句:关联多个数据源,创建一个临时的对象集合
    例:var query = from s in students join c in courses on s.stId equals c.stId where c.courseName == “history” select s.stuName;//查询所有选修了history课的学生名
  • 3)let子句:接收一个表达式的运算并把它赋值给一个需要在其他运算中使用的标识符,是from…let…where片段中的一部分
    例:var query = from a in groupA from b in groupB let sum = a + b where sum < 12 select new(a,b,sum);
  • 4)where子句:表达式中可以有多个where子句
  • 5)orderby子句:将返回的数据进行排序(ascending、descending)
    …… where c.courseName == “history” orderby s.stuName
  • 6)group子句;select的结果按指定的键(key)进行分组,分组本身是可枚举类型的并且可以枚举它的项
    var query = from student in students group student by student.major;
  • 7)select子句:指定所选定的对象哪部分应该被选择,可指定→ a: 整个数据项,b: 数据项的一个字段,c: 数据项中几个字段组成的新对象(或类似其他值)
    var query = from a in groupA from b in groupB let sum = a + b where sum < 12 select new (a, b, sum); //a,b,sum组成的新字段
  • 8)查询延续——into子句:可接受查询的一部分结构并赋予一个名字,从而可以在查询的另一部分中使用
    例:var someInt = from a in groupA
    from b in groupB into groupAandB from c in groupAandB select c;

注意:1、查询表达式语法与SQL(结构查询语言)语法相同。
2、查询语法必须以from子句开头,可以以Select或GroupBy子句结束 。
3、使用各种其他操作,如过滤,连接,分组,排序运算符以构造所需的结果。
4、隐式类型变量 - var可以用于保存LINQ查询的结果。

2.方法语法(Fluent Syntax)(也称流利语法)

主要利用System.Linq.Enumerable类中定义的扩展方法 & Lambda表达式进行查询,类似调用类的扩展方法。
例:var result = ints.Where(p => p % 2 == 0).ToArray();//返回数组中的偶数

3.关于表达式语法和方法语法

CLR只理解方法语法,编译时,CLR会将查询语法转换为方法语法;
大部分方法都有对应的查询形式:如Select()对应select、OrderBy()对应orderby;
部分查询方法在C#中还没有对应的查询语句:如Count()和Max(),只能采用方法语法/方法表达式混合语法。
例:var numQuery = from number in num //查询语法
    where number < 8
    select number;
    var numMethod = num.Where(x => x < 8); //方法语法

4.Lambda表达式(Lambda运算符=>)

可用Lambda运算符“=>”表示查询语句,可减少代码量,使得代码更加的优美简洁。

(1)表达式定义:实际上是一种匿名函数,在Lambda表达式中可以包含语句以及运算等操作。
可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式。
(2)表达式形式(Input Param)=>表达式/{方法体} //参数只有一个时可去掉括号
=>读作goes to,如表达式t=>t.ClassCode='1001',读做goes to ClassCode equal 1001。

1(int[] ints, int item) => ints.Contains(item) 
//使用多个参数要加括号,参数若是var类型则:(ints, item) =>……2() => {Console.WriteLine("hello!");return 1;} 
//{}中可包含多条语句。

(3)List集合中的Lambda表达式的运用
在C#的List集合中,时常需要使用到大量的运算或者筛选等操作,常规的方式是foreach/for循环,其实也可使用Lambda表达式一条语句完成。

例:假设有以下对象:studentList(集合中对象为学生实体Student),
scoreList(成绩实体Score),Student实体(包含几个属性,StudentName,StudentCode,ClassCode,ClassName,BirthDay,Grade。)
a.查询编号为1001的班级里所有学生,并按照学生出生日期升序排列。
var list1001=Studentlist.Where(t=>t.ClassCode==‘1001’).OrderBy(t=>t.BirthDay);
b.查询编号为1001的班级里所有姓【李】的同学,并按出生日期从升序排列。
var list1001=Studentlist.Where(t=>t.ClassCode==‘1001’&&t.StudentName.StartWith(“李”)).OrderBy(t=>t.BirthDay);
c.查询编号1001的班级里,至少一门考试科目成绩低于60分的所有同学。
var list1001=studentList.where(t=>(t.ClassCode==‘1001’)&&(scoreList.Exists(s=>s.ScoreValue<60&&s.StudentCode==t.StudentCode)))

(4)其他常用表达式:

  • var a = studentList.FirstOrDefault(t => t.StudentCode ==
    “10012”);
    //FirstOrDefault返回第一个符合条件的数据,不存在的时候返回Null。
  • var b = studentList.Count(t => t.StudentName == “李世民”);
    //返回符合条件的实体个数
  • var c = studentList.FindAll(t =>
    t.StudentName.Contains(“中”));
    //查找所有名字中含有【中】的实体集合
  • var d = studentList.GroupBy(t =>
    t.ClassCode);
    //对studentList按照ClassCode分组
  • var f = studentList.Max(t => t.BirthDay); //返回最大的出生日期
  • var e = scoreList.Sum(t => t.ScoreValue); //对所有成绩求和
  • var g = scoreList.Average(t => t.ScoreValue); //对所有成绩求平均分
  • var h = studentList.Select(t =>
    t.StudentName).Distinct(); //获取所有的学生姓名,并去除重名

(二)ORM-对象关系映射

ORM——Object Relational Mapping(实体关系模型)
O:Domain Object 领域/业务模型(对应程序中的类)
R:Relational Database 关系型数据库(联系,对应数据库中的关系表)
M:Mapping 映射关系(程序中对象&数据库中关系表的映射关系)
ORM的对应关系表————数据表-模型类;字段-类属性;字段约束-类的属性值;表记录-模型类的实例
避免数据库代码的重复性,大量语句影响程序的扩展性/灵活性
数据持久化(PO):开发过程中不需要实时关注数据的变化
EDM:一个可视化工具,用来生成O\R\M
EF:使用ORM框架,给予ADO.NET开发

(三)EF的三种开发模式/模型

(1)DataBaseFirst(数据库优先)——推荐使用

先建数据库,然后根据数据库生成Model。(在设计器中逆向生成Model,并由Model自动生成所有的类)
即先在数据库中制作存储表,然后通过vs2010从数据库存成概念模型。唯一缺点是需要去建实体对象的partial类,在partial类中设置特性等。
根本差异:【添加ADO.NET实体数据模型时选择数据库生成,在数据结构发生变化时,选择从数据库更新模型
注意:对应的数据库表必须有主键,否则会报错

(2)ModelFirst(模型优先)

先建立实体类,然后根据实体类生成数据库。(在设计器中创建Model,并用Model生成数据库。所有的类由Model自动生成)
即先在vs2010中制作概念模型,然后反向生成数据库存储模型。这种方式不需要partial类,你在写实体类的时候,顺便也会把特性写上。
根本差异:【添加ADO.NET实体数据模型时选择空模型生成,当数据结构发生变化时,选择从模型生成数据库。】

(3)CodeFirst(代码优先)——鸡肋

不建立数据模型也不建立数据库的情况下,通过代码形式新建一个数据库
把Code First模式的两种具体方式独立出来,又分为两种——
a.Code First(New DataBase) :在代码中定义类和映射关系并通过model生成数据库,使用迁移技术更新数据库。
b.Code First(Existing DataBase):在代码中定义类和映射关系,给逆向工程提供工具。
在vs2010手工编写实体模型(Model),并在数据库手工制作存储表,然后即可无需写CRUD(增删改查)即可直接进行数据库操作,代码如下。

(四)EF初级

EF的作用:原本DAL层(DAL和Model)以及BLL层中对DAL的调用,即所有涉及SQL操作的工作全部交由DBcontext类来完成,即操作时数据库时只需要操作DBcontext对象即可

(1)DBFirst方法

操作步骤:

  • 在VS项目中右键添加<ADO.NET实体数据模型>,选择<来自数据库的EF设计器>。
  • 在已建立的数据模型基础上添加新数据模型:双击Models.edmx,在页面右击,选择“从数据库更新模型”,勾选添加(页面会出现新增模型,但Models.tt下没有,此时右击项目选择生成即可)

内容详解:

  • 1.Models.edmx——Models.Context.tt和Models.tt是生成的xml模板文件,在它们之下的文件都是基于这二者产生的
  • 2.Models.edmx——Context.tt——User.cs是生成的类文件,和自建的一样getset
  • 3.DbContext:负责数据&对象互操作(Models.Context.tt——Models.Context.cs——public partial class TestEntities : DbContext)
    关于数据库的增删改查统统通过DbContext来完成。该类型主要包含以下功能:EntitySet、Querying、Change Tracking等
  • 4.EntitySet实体集(DbContext包含所有从数据库表中被映射出来的实体对象的集合,如DbSet<User>对应数据库中的User表,操纵DbSet<User>就相当于操纵User数据表);
    ——Querying:DbContext将LINQ转化为SQL语句并发送到数据库;
    ——Change Tracking:保持变更追踪,当实体发生变化时查询数据库并添加标记

小Tips:
*在SQL中勾选“允许为空”的字段,在EF中会显示Nullable(如:public Mullable string XXX……)
*SQLServer中可以设置列为<自增>,必须为int、decimal等数字类型。勾选“标识规范”中的“是标识”,设置“标识增量”即可。这样在插入数据时可以不管该字段,让它自增

  • 5.使用LINQ进行数据库操作:
    重点:①创建DbContext类的对象,通过它操纵数据库
    ②【DbContext对象.model名】可加点调用Add/Remove/Select/ToList(将实体集转化为集合)

查询:

var result = db.t_Department.Select(s => s).ToList(); 
//也可用db.Department.Where(xxx)

插入:

using (TestEntities db=new TestEntities()) //1.创建DBcontext对象
 {
	t_User usr = new EFtest.t_User(){
    	uID = 4,uName="mopv,ep",
    	uExpireDate=DateTime.Now.AddDays(7)};
    db.t_User.Add(usr); //2.调用Add()方法插入,添加的数据必须以实体模型(比如user)的对象的形式创建
    db.SaveChanges();
}

删除:

var result = db.t_User.FirstOrDefault(s => s.uID == 4);
//remove()中只能指定要删除的那一条对象,当查询结果可能为多条记录时,要用FirstOrDefault()取第一条
db.t_User.Remove(result);//参数必须是一个对象,不能是一个集合

修改:
查询到要修改的实体对象,修改它对应的属性,完成后执行savechanges()

var result = db.t_User.FirstOrDefault(s => s.uID == 4);
result.uName = "哈哈哈";
db.SaveChanges();

(2)用EF执行SQL语句

需要利用DBcontest对象下的Database属性调用以下方法———— db.Database此属性用于操作数据库本身,实现数据的增删改查

  1. ExecuteSqlCommand()

执行SQL语句。即执行给定的DDL/DML命令(适用于创建删除表、增删改)

  • 创建表时,操作成功返回-1,操作失败返回其他值(*LINQ不能创建表)
  • 增删改时,操作成功返回受影响行数,失败返回小于0的值
  1. SQLQuery()

执行查询操作。
返回查询到的结果返回值可以是集合(但不是list类型,可用tolist()方法转换)、单个对象、数字。返回的结果集可以直接遍历,也可用tolist()转换后遍历。

进行复杂的查询时,用EF执行SQL语句性能优于用LINQ编写查询语句(因为LINQ最终会被编译成SQL再执行)

用EF执行SQL语句比ADO.NET方便

创建&删除表

string mystr = "drop table t_Teamleader"; var result = db.Database.ExecuteSqlCommand(mystr);

增删改:

str=“……”,ExecuteSqlCommand(str);
//活用占位符:str = "update t_Teamleader set tEmail=@p1 where tEmail=@p2“;    
SqlParameter[] para = {new SqlParameter("@p1","lilili"),new SqlParameter("@p2","111")}
result = db.Database.ExecuteSqlCommand(mystr, para);//传参

查询操作:

str = "select * from ……";
var result = db.Database.SqlQuery<t_Teamleader>(mysql)
//注意必须要指明泛型<t_Teamleader>(作为返回值类型),否则不能执行

存储过程使用:
引入存储过程后,当成方法使用即可。

var result2 = db.getUserNameByID(0).FirstOrDefault();

(3)CodeFirst

指只需要通过编写代码自动创建模型&数据库,无需使用工具

  • 1.在Models文件夹下创建类,编写类代码
  • 2.新建项,选择ADO.NET实体模型——空CodeFirst模型,命名:XXXEntity
  • 3.当使用时,需要先加命名空间:using 项目名.XXXEntity;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值