一、EntityFramework(简称“EF”)是什么?

在.NET3.5之前,我们经常编写ADO.NET代码或通过封装好的数据库访问层来与数据库进行交互,进行CRUD操作。这种模式下,我们往往需要手写大量的SQL语句,不但麻烦而且容易出错。在这种背景下,后来微软发布了EntityFramework框架。

EF是一种开源的ORM框架,适合.Net开发,用领域对象(Domain Object)来处理数据,而不需要关注具体的数据库中表和列。

EF框架的开发模式主要包括两种DBFirst和CodeFirst,一种是基于已有的数据库进行开发,一种是基于类生成数据库进行开发。本文我们主要和大家一起学习下DBFirst模式。

二、EF架构组成

       1、EDM(实体数据模型): EDM包含三个主要部分——概念模型,映射和存储模型。

    概念模型(entity): 概念模型包含了模型类和它们之间的关系。 这将是独立于数据库表设计。

    存储模型(data): 存储模型是数据库设计模型,包括表、视图、存储过程、以及它们之间的关系和钥匙。

    映射(mapping): 映射由概念模型如何映射到存储模型的信息组成。

  2、LINQ To Entity(L2E): L2E是一种的查询实体对象的语言, 它返回在概念模型中定义的实体。

  3、Entity SQL: Entity SQL是一个类似于L2E的查询语言。 然而,它比L2E更加复杂。

  4、Object Services(对象服务):对象服务是访问数据库中的数据并返回数据的主要入口点。它负责数据实例化,把Entity Client Data Provider(下一层)的数据转换成实体对象。

  5、Entity Client Data Provider:主要职责是将L2E或Entity Sql转换成数据库可以识别的Sql查询语句,它通过ADO.Net Data Provider向数据库发送或者索取数据。

  6、ADO.Net Data Provider:使用标准的Ado.net与数据库通信。

三、实战——基础用法

1.创建web项目

2.基于现有数据库添加模型

1)选择ADO.NET数据模型

2)选择来自数据库的EF设计器

3)新建数据库连接信息(服务器,数据库,用户名和密码)

4)选择你需要的数据表,视图或存储过程

完成以上操作后,点击完成,EF框架会自动帮你在项目中创建已.edmx为后缀的文件。该文件下包含一个继承DbContext类的上下文实例(DbContext是实体类和数据库之间的桥梁)和基于数据库创建的实体模型。

另外,在项目的web.config文件中自动帮我们生成的链接字符串,大家不要轻易去改动,否则会引起报错。

 <connectionStrings>
<add name="ConnectionString" connectionString="metadata=res://*/EntityDomainModel.csdl|res://*/EntityDomainModel.ssdl|res://*/EntityDomainModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=TEST;persist security info=True;user id=sa;password=123456;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

3.继承DbContext类的上下文实例MyDbContext

 1 public partial class MyDbContext : DbContext
2 {
3 public MyDbContext()
4 : base("name=ConnectionString")
5 {
6 }
7
8 protected override void OnModelCreating(DbModelBuilder modelBuilder)
9 {
10 throw new UnintentionalCodeFirstException();
11 }
12 /// <summary>
13 /// Person类
14 /// </summary>
15 public virtual DbSet<Person> Person { get; set; }
16 /// <summary>
17 /// PersonAddress类
18 /// </summary>
19 public virtual DbSet<PersonAddress> PersonAddress { get; set; }
20 }

其中Person和PersonAddress两个实体是我们在选择数据库表后,EF框架生成的实体类。

要点:数据库上下文要想操作数据表,这里就必须要在DbContext中加入DBSet<具体数据表对应的实体类>。当然DBFirst模式下,EF创建实体后会帮我们完成这一步操作。

4.基于数据库的数据模型

    public partial class Person
{
public string ID { get; set; }
public string Name { get; set; }
public Nullable<int> Age { get; set; }
public Nullable<System.DateTime> Create_Date { get; set; }
} public partial class PersonAddress
{
public string ID { get; set; }
public string PersonId { get; set; }
public string Address { get; set; }
public Nullable<System.DateTime> Create_Date { get; set; }
}

5.API接口实现

这里我们以接口的方式,展示下EF基础用法。主要包括查询(单表查询,多表关联查询,条件查询)、新增、更新、删除。

编程中我们推荐LINQ语法下的lamda表达式用法,看起来简洁明了

5.1单表查询

        // GET api/values
public string Get()
{
//单表查询
var person = dbContext.Person.Where(x => x.Name == "张三").FirstOrDefault();
if (person == null)
return "Fail";
return "Success";
}

where条件查询,FirstOrDefault()返回查询结果中的第一条记录(如果没有记录返回NULL)

5.2多表关联查询(INNER JOIN)

        // GET api/values/Inner
[System.Web.Http.Route("Inner")]
public string GetInner()
{
//Inner join 查询
var result = dbContext.Person.Join(dbContext.PersonAddress, x => x.ID, y => y.PersonId, (x, y) => new { x, y });//join中的第四个参数为查询的结果
var sql = result.ToString(); //获取sql语句
var list = result.Select(query => new Person_OutputModel { ID = query.x.ID, Name = query.x.Name, Age = query.x.Age, Address = query.y.Address, Create_Date = query.x.Create_Date }).ToList();
return "Success:" + list?[0].ID;
}

1)实现表Person和PersonAddress之间的INNER JOIN关联查询

2)Join()方法:参数1:关联查询的副表;  参数2:主表的关联条件列;  参数3:副表的关联条件列;  参数4:查询返回的结果集

3)LINQ表达式转SQL语句: result.ToString()

4)Select选择需要的表信息。

5.3多表关联查询(LEFT JOIN)

        // GET api/values/LeftJoin
[System.Web.Http.Route("LeftJoin")]
public string GetLeft()
{
//Left join查询
var result = dbContext.Person.GroupJoin(dbContext.PersonAddress, x => x.ID, y => y.PersonId, (x, y) => new { x, y });
var sql = result.ToString(); //获取sql语句
var list = result.Select(query => new Person_LeftJoin_OutputModel { ID = query.x.ID, Name = query.x.Name, Age = query.x.Age, Create_Date = query.x.Create_Date, lstAddress = query.y.ToList() }).ToList();
return "Success:" + list?[0].ID;
}

1)GroupJoin()方法返回的结果集中,返回的副表PersonAddress是一个集合IEnumerable。也就说结果集中Person和PersonAddress是一对多,而Join()中是一对一的。

2)GroupJoin()方法的用法和Join()一样,我们来看下输出的SQL语句:

表Person和PersonAddress关联用的是LEFT OUTER JOIN。

5.4条件查询

        // GET api/values/JoinWhere/1
[System.Web.Http.Route("JoinWhere/{ID}")]
public string GetWhere(string ID)
{
//join +副表条件查询
var result = dbContext.Person.GroupJoin(dbContext.PersonAddress.Where(addr => addr.ID == ID), x => x.ID, y => y.PersonId, (x, y) => new { x, y });
var sql = result.ToString(); //获取sql语句
var list = result.Select(query => new Person_LeftJoin_OutputModel { ID = query.x.ID, Name = query.x.Name, Age = query.x.Age, Create_Date = query.x.Create_Date, lstAddress = query.y.ToList() }).ToList();
return "Success:" + list?[0].ID;
} // GET api/values/JoinWhere2/张三
[System.Web.Http.Route("JoinWhere2/{Name}")]
public string GetWhere2(string Name)
{
//join +主表条件查询
var result = dbContext.Person.Where(l => l.Name == Name).Join(dbContext.PersonAddress, x => x.ID, y => y.PersonId, (x, y) => new { x, y });
var sql = result.ToString(); //获取sql语句
var list = result.Select(query => new Person_OutputModel { ID = query.x.ID, Name = query.x.Name, Age = query.x.Age, Create_Date = query.x.Create_Date, Address = query.y.Address }).ToList();
return "Success:" + list?[0].ID;
}

1)Left Join+副表条件查询,SQL输出:

我们发现副表的查询条件ID被当做两张表查询时Join条件使用,LEFT OUTER JOIN [dbo].[PersonAddress] AS [Extent2] ON ([Extent2].[ID] = @p__linq__0) AND ([Extent1].[ID] = [Extent2].[PersonId])

2)Inner Join+主表条件查询,SQL输出:

我们发现主表的查询条件Name被当做两张表查询时where条件使用,WHERE ([Extent1].[Name] = @p__linq__0)

5.5新增

        // POST api/values
public JsonResult Post(Person_InputModel model)
{
//新增人员
Person person = new Person
{
ID = Guid.NewGuid().ToString(),
Name = model.Name,
Age = model.Age,
Create_Date = DateTime.Now
};
dbContext.Person.Add(person);
if (!string.IsNullOrEmpty(model.Address))
{
//新增人员地址
PersonAddress address = new PersonAddress
{
ID = Guid.NewGuid().ToString(),
PersonId = person.ID,
Address = model.Address,
Create_Date = DateTime.Now
};
dbContext.PersonAddress.Add(address);
}
//执行新增操作
dbContext.SaveChanges();
return new JsonResult { Data = "Success" };
}

1)使用Add()方法

2)dbContext.SaveChanges()实现对当前操作对象的状态(新增,修改,删除)更新。SaveChanges()方法内部以事务的方式执行。

5.6更新

        // PUT api/values/5
public string Put([FromBody]string name)
{
var person = dbContext.Person.Where(x => x.Name == name).FirstOrDefault();
if (person == null)
return "Fail";
person.Age = person.Age + 1;
dbContext.SaveChanges();
return "Success";
}

EF的更新操作中,直接更新数据即可person.Age = person.Age + 1,当前数据库上下文会保存对象的变更状态。

5.7删除

        // DELETE api/values/5
public string Delete(string id)
{
var personAddr = dbContext.PersonAddress.Where(x => x.ID == id).FirstOrDefault();
if (personAddr == null)
return "Fail";
dbContext.PersonAddress.Remove(personAddr);
dbContext.SaveChanges();
return "Success";
}

使用Remove()方法进行删除。

EntityFramwork基础用法的更多相关文章

  1. PropertyGrid控件由浅入深(二):基础用法

    目录 PropertyGrid控件由浅入深(一):文章大纲 PropertyGrid控件由浅入深(二):基础用法 控件的外观构成 控件的外观构成如下图所示: PropertyGrid控件包含以下几个要 ...

  2. logstash安装与基础用法

    若是搭建elk,建议先安装好elasticsearch 来自官网,版本为2.3 wget -c https://download.elastic.co/logstash/logstash/packag ...

  3. elasticsearch安装与基础用法

    来自官网,版本为2.3 注意elasticsearch依赖jdk,2.3依赖jdk7 下载rpm包并安装 wget -c https://download.elastic.co/elasticsear ...

  4. BigDecimal最基础用法

    BigDecimal最基础用法 用字符串生成的BigDecimal是不会丢精度的. 简单除法. public class DemoBigDecimal { public static void mai ...

  5. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

  6. Smarty基础用法

    一.Smarty基础用法: 1.基础用法如下 include './smarty/Smarty.class.php';//引入smarty类 $smarty = new Smarty();//实例化s ...

  7. 前端自动化测试神器-Katalon的基础用法

    前言 最近由于在工作中需要通过Web端的功能进行一次大批量的操作,数据量大概在5000左右,如果手动处理, 完成一条数据的操作用时在20秒左右的话,大概需要4-5个人/天的工作量(假设一天8小时的工作 ...

  8. Bootstrap fileinput:文件上传插件的基础用法

    官网地址:http://plugins.krajee.com/ 官网提供的样例:http://plugins.krajee.com/file-input/demo 基础用法一 导入核心CSS及JS文件 ...

  9. asyncio 基础用法

    asyncio 基础用法 python也是在python 3.4中引入了协程的概念.也通过这次整理更加深刻理解这个模块的使用 asyncio 是干什么的? asyncio是Python 3.4版本引入 ...

随机推荐

  1. git 如何比较不同分支的差异

    前两天,良许在做集成的时候碰到了一件闹心事.事情是这样的,良许的一位同事不小心把一个错误的 dev 分支 merge 到了 master 分支上,导致了良许编译不通过.于是,我们需要将版本回退到 me ...

  2. BootStrap-select插件动态添加option无法显示

    问题描述: 在使用bootstrap-select插件时出现下拉框无法显示动态追加的option,经过查看element元素发现,select标签已经append进去了所需的option选项,但是页面 ...

  3. 跟着尚硅谷系统学习Docker-【day01】

    day01-20200710   p1.基础知识   鲸鱼背上有一些集装箱   学习docker得基础知识   1.强制:熟悉Linux命令和相关背景知识 2.建议有maven和git的相关知识   ...

  4. Oracle WITH 语句 语法

    With语句可以在查询中做成一个临时表/View,用意是在接下来的SQL中重用,而不需再写一遍. With Clause方法的优点: 增加了SQL的易读性,如果构造了多个子查询,结构会更清晰. 示例: ...

  5. Java单例模式的实现与破坏

    单例模式是一种设计模式,是在整个运行过程中只需要产生一个实例.那么怎样去创建呢,以下提供了几种方案. 一.创建单例对象 懒汉式 public class TestSingleton { // 构造方法 ...

  6. Mysql主从分离与双机热备超详细配置

    一.概述 本例是在Windows环境,基于一台已经安装好的Mysql57,在本机安装第二台Mysql57服务. 读完本篇内容,你可以了解到Mysql的主从分离与双机热备的知识,以及配置期间问题的解决方 ...

  7. Javaweb中的请求路径的相关总结

    重定向和转发相对路径和绝对路径问题 ​ 注意:转发和重定向的URLString前有加 / 为绝对路径 反之为相对路径 1.假设通过表单请求指定的Url资源 action="LoginServ ...

  8. %s 表示格式化一个对象为字符

    比如: name=“good” print('%s'%name)会打印出good print('%3s'%name)  会打印出good,当%和s之间的数字,小于字符串长度时,实际打印出字符串的长度 ...

  9. 如何使用 TDengine 2.0 最新开源的集群功能?

    导读:8月3日,TDengine 发布了 v2.0 版本,这次更新最大的亮点是,我们将分布式集群功能开源.开源后,引起了很大反响,又连续几天在 GitHub 趋势榜排名第一.不少关注TDengine的 ...

  10. H5C3综合案例

    案例:实现步骤 1. 搭建HTML结构 <section> <div></div> <div></div> <div></ ...