• EntityFramwork基础用法


    一、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()方法进行删除。

  • 相关阅读:
    反射&异常
    成员方法
    继承&多态
    面向对象
    常用模块
    软件目录结构规范
    内置函数
    生产器&迭代器
    装饰器
    函数
  • 原文地址:https://www.cnblogs.com/chenxf1117/p/13750784.html
Copyright © 2020-2023  润新知