.NET EF(Entity Framework)详解

一丶Entity Framework

(一)EF简介

(1)ORM:Object Relation Mapping ,通俗说:用操作对象的方式来操作数据库。
(2)插入数据库不再是执行Insert,而是类似于Person p = new Person();p.Age=3;p.Name=“英莱特”;db.Save§;这样的做法。
(3)ORM工具有很多Dapper、PetaPoco、NHibernate,最首推的还是微软官方的Entity Framework,简称EF。
(4)EF底层仍然是对ADO.Net的封装。EF支持SQLServer、MYSQL、Oracle、Sqlite等所有主流数据库。
(5)使用EF进行数据库开发的时候有两个东西建:建数据库(T_Persons),建模型类(Person)。根据这两种创建的先后顺序有EF的三种创建方法:

  • DataBase First(数据库优先):先创建数据库表,然后自动生成EDM文件,EDM文件生成模型类。简单展示一下DataBase First 的使用。
  • Model First(模型优先):先创建Edm文件,Edm文件自动生成模型类和数据库;
  • Code First(代码优先):程序员自己写模型类,然后自动生成数据库。没有Edm。
    DataBase First 简单、方便,但是当项目大了之后会非常痛苦;

Code First 入门门槛高,但是适合于大项目。
Model First……

无论哪种First,一旦创建好了数据库、模型类之后,后面的用法都是一样的。业界都是推荐使用Code First,新版的EF中只支持Code First,因此我们这里只讲Code First。

(6)Code First的微软的推荐用法是程序员只写模型类,数据库由EF 帮我们生成,当修改模型类之后,EF 使用“DB Migration”自动帮我们更改数据库。但是这种做法太激进,不适合很多大项目的开发流程和优化,只适合于项目的初始开发阶段。Java的Hibernate 中也有类似的DDL2SQL 技术,但是也是用的较少。“DB Migration”也不利于理解EF,因此在初学阶段,我们将会禁用“DB Migration”,采用更实际的“手动建数据库和模型类”的方式。

(7)如果大家用过 NHibernate 等ORM 工具的话,会发现开发过程特别麻烦,需要在配置文件中指定模型类属性和数据库字段的对应关系,哪怕名字完全也一样也要手动配置。使用过Java 中Struts、Spring 等技术的同学也有过类似“配置文件地狱”的感觉。 像ASP.Net MVC 一样,EF 也是采用“约定大于配置”这样的框架设计原则,省去了很多配置,能用约定就不要自己配置。

在.Net Framework SP1微软包含一个实体框架(Entity Framework),此框架可以理解成微软的一个ORM产品。用于支持开发人员通过对概念性应用程序模型编程(而不是直接对关系存储架构编程)来创建数据访问应用程序。目标是降低面向数据的应用程序所需的代码量并减轻维护工作。

(二)Entity Framework应用程序有以下优点:

(1)应用程序可以通过更加以应用程序为中心的概念性模型(包括具有继承性、复杂成员和关系的类型)来工作。
(2)应用程序不再对特定的数据引擎或存储架构具有硬编码依赖性。
(3)可以在不更改应用程序代码的情况下更改概念性模型与特定于存储的架构之间的映射。
(4)开发人员可以使用可映射到各种存储架构(可能在不同的数据库管理系统中实现)的一致的应用程序对象模型。
(5)多个概念性模型可以映射到同一个存储架构。
(6)语言集成查询支持可为查询提供针对概念性模型的编译时语法验证。

实体框架Entity Framework是 DO.NET中的一组支持开发面向数据的软件应用程序的技术。在EF中的实体数据模型(EDM)由以下三种模型和具有相应文件扩展名的映射文件进行定义。

  • 概念架构定义语言文件 (.csdl) – 定义概念模型。

  • 存储架构定义语言文件 (.ssdl) – 定义存储模型(又称逻辑模型)。

  • 映射规范语言文件 (.msl) – 定义存储模型与概念模型之间的映射。
    实体框架使用这些基于XML的模型和映射文件将对概念模型中的实体和关系的创建、读取、更新和删除操作转换为数据源中的等效操作。EDM甚至支持将概念模型中的实体映射到数据源中的存储过程。它提供以下方式用于查询 EDM 并返回对象:

  • LINQ to Entities–提供语言集成查询(LINQ)支持用于查询在概念模型中定义的实体类型。

  • Entity SQL – 与存储无关的SQL方言,直接使用概念模型中的实体并支持诸如继承和关系等 EDM 功能。

  • 查询生成器方法 --可以使用LINQ风格的查询方法构造 Entity SQL 查询。

(三)相关知识复习

(1)var类型推断:var p =new Person();
(2)匿名类型。var a =new {p.Name,Age=5,Gender=p.Gender,Name1=a.Name};//{p.Name}=={Name=p.Name}
(3)给新创建对象的属性赋值的简化方法:Person p = new Person{Name=“tom”,Age=5};等价于Person p = new Person();p.Name=“tom”;p.Age=5;

(四)lambda表达式:

函数式编程,在Entity framework编程中用的很多

Action<int> al= delegate(int i) { Console.Writeline(i); };

可以简化成(=>读作goes to) :

Action< int> a2 = (inti) = > { Console.Writeline(i); };

还可以省略参数类型(编译器会自动根据委托类型推断):

Action< int> a3 = (i) = > { Console.Writeline(i); };

如果只有一个参数还可以省略参数的小括号(多个参数不行)

Action<int> a4 = i = > { Console.Writeline(i); };

如果委托有返回值,并且方法体只有一行代码,这一行代码还是返回值,那么就可以连方法的大括号和return都省略:

Func<int,int,string> fl= delegate(int i, int j) { return "结果是" + (i + j); };
Func<int,int,string> f2= (i,j)=>"结果是"+ (i+ j);

(五)集合常用扩展方法

where (支持委托)、Select (支持委托)、Max 、Min 、OrderBy

First (获取第一个,如果一个都没有则异常)

FirstOrDefault (获取第一个,如果—个都没有则返回默认值)

Single (获取唯一一个,如果没有或者有多个则异常)

SingleOrDefoult (获取唯一一个, 如果没有则返回默认值,如果有多个则异常)

注意lambda中照样要避免变量重名的问题:var p =persons.Where(p => p.Name ==“yltedu.com”).First();

(六)高级集合扩展方法

//学生
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salary { get; set; }
public override string ToString()
{
return string.Format("Name={0},Age={1},Gender={2},Salary={3}",Name, Age, Gender, Salary);
}
}

//老师
public class Teacher
{
public Teacher()
{
this.Students=new List<Person>();
}
public string Name { get; set; }
public List<Person> Students { get; set; }
}
var s0 =new Person { Name="tom",Age=3,Gender=true,Salary=6000};
var s1 = new Person { Name = "jerry", Age = 8, Gender = true, Salary = 5000 };
var s2 = new Person { Name = "jim", Age = 3, Gender = true, Salary = 3000 };
var s3 = new Person { Name = "lily", Age = 5, Gender = false, Salary = 9000 };
var s4 = new Person { Name = "lucy", Age = 6, Gender = false, Salary = 2000 };
var s5 = new Person { Name = "kimi", Age = 5, Gender = true, Salary = 1000 };
List<Person> list = new List<Person>();
list.Add(s0);
list.Add(s1);
list.Add(s2);
list.Add(s3);
list.Add(s4);
list.Add(s5);
Teacher t1 = new Teacher { Name="英莱特.net"};
t1.Students.Add(s1);
t1.Students.Add(s2);
Teacher t2 = new Teacher { Name = "英莱特Python" };
t2.Students.Add(s2);
t2.Students.Add(s3);
t2.Students.Add(s5);
Teacher[] teachers = { t1,t2};

(1)Any(),判断集合是否包含元素,返回值是bool,一般比Cout()>0 效率高。Any还可以指定条件表达式。

bool b = list.Any(p => p.Age > 50); 等价于bool b =list.Where(p=>p.Age>50).Any();

(2)Distinct(),剔除完全重复数据。(*)注意自定义对象的Equals 问题:需要重写Equals 和GetHashCode 方法来进行内容比较。
(3)排序:升序list.OrderBy(p=>p.Age);降序list.OrderByDescending(p=>p.Age)。指定多个排序规 则,而不是多个OrderBy,而是:list.OrderByDescending(p=>p.Age).ThenBy(p=>p.Salary),也支 持ThenByDescending()。注意这些操作不会影响原始的集合数据。
(4)Skip(n)跳过前n条数据;
(5)Take(n)获取最多n条数据,如果不足n条也不会报错。常用来分页获取数据。
(6)list.Skip(3).Take(2)跳过前3条数据获取2条数据。
(7)Except(items1)排除当前集合中在items1中存在的元素。用int数组举例。
(8)Union(items1)把当前集合和items1中组合。用int 数组举例。
(9)Intersect(items1) 把当前集合和items1 中取交集。用int 数组举例。
(10)分组

foreach(var g in list.GroupBy(p => p.Age))
{
    Console.WriteLine(g.Key+":"+g.Average(p=>p.Salary));
}

(11)SelectMany:把集合中每个对象的另外集合属性的值重新拼接为一个新的集合

foreach(var s in teachers.SelectMany(t => t.Students))
{
    Console.WriteLine(s);//每个元素都是Person
}
}

注意不会去重,如果需要去重要自己再次调用Distinct()
(12)Join

class Master
{
    public long Id { get; set; }
    public string Name { get; set; }
}
class Dog
{
    public long Id { get; set; }
    public long MasterId { get; set; }
   public string Name { get; set; }
}
Master m1 = new Master { Id = 1, Name = "英莱特" };
Master m2 = new Master { Id = 2, Name = "比尔盖茨" };
Master m3 = new Master { Id = 3, Name = "周星驰" };
Master[] masters = { m1,m2,m3};
Dog d1 = new Dog { Id = 1, MasterId = 3, Name = "旺财" };
Dog d2 = new Dog { Id = 2, MasterId = 3, Name = "汪汪" };
Dog d3 = new Dog { Id = 3, MasterId = 1, Name = "京巴" };
Dog d4 = new Dog { Id = 4, MasterId = 2, Name = "泰迪" };
Dog d5 = new Dog { Id = 5, MasterId = 1, Name = "中华田园" };
Dog[] dogs = { d1, d2, d3, d4, d5 };

Join 可以实现和数据库一样的Join 效果,对有关联关系的数据进行联合查询 下面的语句查询所有Id=1 的狗,并且查询狗的主人的姓名。

var result = dogs.Where(d => d.Id > 1).Join(masters, d => d.MasterId, m => m.Id,(d,m)=>new {DogName=d.Name,MasterName=m.Name});
foreach(var item in result)
{
    Console.WriteLine(item.DogName+","+item.MasterName);
}

(七)EF 的安装

(1)基础阶段用控制台项目。使用NuGet 安装EntityFramework。会自动在App.config中增加两个entityFramework 相关配置段;
(2)在 web.config 中配置连接字符串

<add name="conn1" connectionString="Data Source=.;Initial Catalog=test1;UserID=sa;Password=123" providerName="System.Data.SqlClient" />

易错点:不能忘了写providerName="System.Data.SqlClient"增加两个entityFramework 相关配置段;

(八)EF 简单DataAnnotations 实体配置

(1)数据库中建表T_Perons,有Id(主键,自动增长)、Name、CreateDateTime字段。
(2)创建Person类[Table(“T_Persons”)]因为类名和表名不一样,所以要使用Table标注

  [Table("T_Persons")]
    public class Person
  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值