一、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. Webpack 入门指迷

    大概算是一份教程吧, 只不过效果肯定不如视频演示之类的好..Webpack 最近在英文社区上经常看到, 留了心, 但进一步了解是通过下边的视频:视频: How Instagram.com Works, ...

  2. GitHub 热点速览 Vol.36:当股票遇到机器学习,异常股无所遁形

    作者:HelloGitHub-小鱼干 摘要:虽然上周的 GitHub Trending 榜新项目寥寥无几,但胜在表现不俗,例如:通过机器学习来检测异常股票的项目 Surpriver,还有腾讯开源的管理 ...

  3. 外包公司派遣到网易,上班地点网易大厦,转正后工资8k-10k,13薪,包三餐,值得去吗?

    作为一个人,我们必须时时刻刻清醒地看待自己,做到不卑不亢才能坚强地活下去. 请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/i ...

  4. Vue和d3.js(v4)力导向图force结合使用,v3版本升级v4【一】

    前段时间因为参与项目涉密,所以一直没有更新博客,有些博友给我私信或者留言要部分博文的源码,因为我的电脑更换,demo的源码没有备份 所以无法提供.大家可针对具体问题问我,有空我定会回复的.另外转发文章 ...

  5. Linux驱动之GPIO子系统和pinctrl子系统

    前期知识   1.如何编写一个简单的Linux驱动(一)--驱动的基本框架   2.如何编写一个简单的Linux驱动(二)--设备操作集file_operations   3.如何编写一个简单的Lin ...

  6. matlab中的多项式计算

    在做多项式加法的时候需要做多项式扩展.这里将g1扩展到与f等长 多项式的乘积,是两个多项式之和减1, 多项式求导函数:ployder() 先建立两个多项式,再求a的导函数 在计算两个多项式乘积的导函数 ...

  7. Github 个人首页的 README,这样玩儿~

    本文首发于 Ficow Shen's Blog,原文地址: Github 个人首页的 README,这样玩儿~. 内容概览 前言 创建仓库 修改 README 的内容 总结 前言 大家最近有没有发现这 ...

  8. Redis的五大数据类型以及key的相关操作命令

    Redis的五大数据类型 redis的数据都是以key/value存储,所以说,五大类型指的是value的数据类型 String 字符串,作为redis的最基本数据类型 redis中的string类型 ...

  9. 二分类问题续 - 【老鱼学tensorflow2】

    前面我们针对电影评论编写了二分类问题的解决方案. 这里对前面的这个方案进行一些改进. 分批训练 model.fit(x_train, y_train, epochs=20, batch_size=51 ...

  10. 对之前IoT项目的完善

    博文有点长,因为是两个大项目(四个小项目)放一起了,不过都很适合新手小白(有源程序的情况),也可以再接 OLED 屏,就是前几篇博客的操作 一.esp8266 读取 DHT11 数据并通过微信小程序发 ...