Entity Framework4.1实现动态多条件查询、分页和排序
- 格式:doc
- 大小:62.00 KB
- 文档页数:5
EntityFramework中实现查询的⼏种⽅法在介绍⼏种⽅法前,献上⼀张图,希望图的作者不要追究我的盗图之过。
本⽂的内容是我⾃学时的笔记,⾃学的内容来⾃⽹络。
⼿打的代码,切不可直接复制过去⽤,会有好多错别字什么的。
Entity SQL类似于SQL语句, SELECT VALUE c FROM Entities.Contacts VALUE关键字表⽰返回的是⼀个对象,原⽂是return an object,not a row. Used when only a single item is selected.Entities.Contacts就是⼀个EDM(Entity Data Model)LINQ to Entities LINQ to Entities 可以看做是LINQ to Object的⼀个变种,通过LINQ来查询来查询EDM,在底层使⽤Object Services来完成其功能。
Object Services:是⼀组⽤于查询实体数据模型的类,它可以将这些查询结果转化为强类型的CLR对象。
Object Services也可以执⾏EntitySQL命令。
通过EntitySQK=l调⽤Object Services⽰例 var queryString="SELECT VALUE c FROM Entitis.Contacts AS c WHERE ='XV'"; ObjectQuery<Contact> contacts=context.CreateQuery<Contact>(queryString);Entity Client 从本⽂开头的图中,很容易就可以知道不管是使⽤EntitySQL还是LINQ to Entities,最后都要以来EntityClient来完成其⼯作。
当然,也可以直接使⽤EntityClient, 通过 EntitySQL,性能较⾼,但要⼿动跟踪数据的修改情况。
【SpringData系列学习】SpringDataJPA⾃定义查询,分页,排序,条件查询Spring Boot Jpa 默认提供 CURD 的⽅法等⽅法,在⽇常中往往时⽆法满⾜我们业务的要求,本章节通过⾃定义简单查询案例进⾏讲解。
快速上⼿项⽬中的pom.xml、application.properties与 Chapter1 相同实体类映射数据库表user 实体类@Entitypublic class User implements Serializable {private static final long serialVersionUID = -390763540622907853L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private Integer age;private String email;// 省略构造器 set/get}⾃定义简单查询spring data 内部基础架构中有个根据⽅法名的查询⽣成器机制,对于在存储库的实体上构建约束查询很有⽤。
该机制⽅法的前缀有find…By、read…By、query…By、count…By 和get…By,从这些⽅法可以分析它的其余部分(实体⾥⾯的字段)。
引⼊⼦句可以包含其他表达式,例如在Distinct要创建的查询上设置不同的标志。
然⽽,第⼀个By作为分隔符来指⽰实际标准的开始。
在⼀个⾮常基本的⽔平上,你可以定义实体性条件,并与它们串联(And和Or)。
注:此段来⾃《Spring Data JPA 从⼊门到精通》。
继承 PagingAndSortingRepositorypublic interface UserPagingRepository extends PagingAndSortingRepository<User, Long> {// 通过姓名查找List<User> findByName(String name);// 通过姓名查找List<User> queryByName(String name);// 通过姓名或者邮箱查找List<User> findByNameOrEmail(String name,String email);// 计算某⼀个 age 的数量int countByAge(int age);}测试类路径:src/test/java/com/mtcarpenter/chapter2/repository/UserPagingRepositoryTest.java@RunWith(SpringRunner.class)@SpringBootTestpublic class UserPagingRepositoryTest {/*** ⽇志对象*/private Logger logger = LoggerFactory.getLogger(UserPagingRepositoryTest.class);@Autowiredprivate UserPagingRepository userPagingRepository;@Beforepublic void save() {("新增数据 result = {}", userPagingRepository.save(new User("⼩⽶", 9,"a@")));("新增数据 result = {}", userPagingRepository.save(new User("张三", 16,"b@")));("新增数据 result = {}", userPagingRepository.save(new User("三哥", 12,"c@")));("新增数据 result = {}", userPagingRepository.save(new User("⽶⼆", 13,"e@")));("新增数据 result = {}", userPagingRepository.save(new User("阿三", 12,"f@")));("新增数据 result = {}", userPagingRepository.save(new User("张三", 12,"g@")));("新增数据 result = {}", userPagingRepository.save(new User("⽶⼆", 8,"h@")));}@Testpublic void find(){("通过姓名查找(findByName) result = {}", userPagingRepository.findByName("张三"));("通过姓名查找(queryByName) result = {}", userPagingRepository.queryByName("张三"));("通过姓名或者邮箱(findByNameOrEmail) 查找 result = {}", userPagingRepository.findByNameOrEmail("张三","f@"));("通过某⼀个 age 的数量(countByAge) result = {}", userPagingRepository.countByAge(12));}}@Before会在@test之前运⾏。
使用Entity Framework进行数据库操作的实用技巧在如今的软件开发中,数据库操作是不可或缺的一部分。
Entity Framework (EF) 是一种常见的对象关系映射 (ORM) 工具,它能够将对象模型映射到数据库中的表结构,提供了便捷快速的数据库操作功能。
本文将介绍一些使用EF进行数据库操作的实用技巧,帮助开发者更好地利用这一工具。
1. 使用Code First开发EF有三种开发模式:Database First、Model First和Code First。
其中,Code First是一个优雅且灵活的方式。
通过编写实体类和配置文件,开发者可以根据实际需求创建数据库表。
这种模式使开发人员能够更加专注于业务逻辑而不必关注数据库细节。
2. 使用迁移在实际的开发过程中,数据库结构可能会频繁变动。
EF提供了迁移(Migration) 功能,用于在数据库结构发生变化时,自动更新数据库。
通过创建并应用迁移脚本,可以保证数据库结构和代码模型保持一致。
3. 使用延迟加载EF默认启用了延迟加载功能,这意味着只有在需要时才会加载相关的导航属性。
开发者可以利用这一特性,高效地获取数据。
同时,也要注意使用Include方法预加载需要的导航属性,避免多次访问数据库。
4. 使用LINQ查询EF支持使用LINQ (Language Integrated Query) 进行数据库查询。
利用LINQ,开发者可以在代码中以类似于SQL的方式进行查询,从而减少了手写SQL语句的工作量。
此外,使用LINQ还能够提高代码的可读性和维护性。
5. 使用事务在需要保证数据库一致性的操作中,开发者可以使用EF的事务机制。
通过使用TransactionScope类,在代码中开启和提交事务,可以确保多个操作在一个事务中进行,要么全部成功,要么全部回滚。
这对于数据的完整性和稳定性至关重要。
6. 使用存储过程和函数尽管EF提供了强大的LINQ查询功能,但在某些情况下,存储过程和函数仍然是一种更加高效和灵活的解决方案。
Entity Framework 是一个针对 .NET 开发框架的数据访问技术。
它支持 .NET Framework 和 .NET Core,可以让开发人员使用面向对象的方式来处理数据库操作,从而提高开发效率,减少重复的工作,降低出错的概率。
本文将介绍 Entity Framework 的基本概念、使用方法和最佳实践,帮助读者更好地理解和使用 Entity Framework。
一、Entity Framework 的基本概念Entity Framework 是一种对象关系映射(ORM)框架,它将数据库中的表映射为 .NET 中的对象,开发人员可以直接通过这些对象来进行数据库操作,而不必编写复杂的 SQL 语句。
在 Entity Framework 中,数据库中的每张表都会映射为一个实体类,表中的每条记录会映射为这个实体类的一个实例。
这种方式让开发人员更加专注于业务逻辑的实现,而不必过多地关注数据库操作的细节。
二、Entity Framework 的使用方法1. 创建 Entity Framework 数据库上下文在使用 Entity Framework 之前,首先需要创建一个数据库上下文(DbContext)类。
这个类是连接 .NET 代码和数据库之间的桥梁,负责管理数据库连接、执行 CRUD 操作等。
可以通过继承DbContext 来创建自己的数据库上下文类,并在类中定义每张表对应的 DbSet 属性。
例如:```csharppublic class MyDbContext : DbContext{public DbSet<User> Users { get; set; }public DbSet<Order> Orders { get; set; }// 其他 DbSet 属性}```2. 配置 Entity Framework在使用 Entity Framework 时,需要进行一些配置工作,以便让框架知道如何映射数据库和 .NET 对象之间的关系。
JPA多条件复杂SQL动态分页查询概述 ORM映射为我们带来便利的同时,也失去了较⼤灵活性,如果SQL较复杂,要进⾏动态查询,那必定是⼀件头疼的事情(也可能是lz还没发现好的⽅法),记录下⾃⼰⽤的三种复杂查询⽅式。
环境springBootIDEA2017.3.4JDK8pom.xml<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.xmlxy</groupId><artifactId>seasgame</artifactId><version>0.0.1-SNAPSHOT</version><name>seasgame</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--数据库连接--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 热启动等 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!--Java bean 实体--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--swagger2 API 测试⼯具 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!--安全框架认证--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.2.2</version><classifier>jdk15</classifier></dependency><!--汉字转拼⾳--><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version></dependency><!-- thymeleaf模板 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>移除嵌⼊式tomcat插件<exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency>--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies><packaging>war</packaging><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins><finalName>seasgame</finalName><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><encoding>${project.build.sourceEncoding}</encoding><source>1.7</source><target>1.7</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><testFailureIgnore>true</testFailureIgnore></configuration></plugin></plugins></pluginManagement></build></project>@Query当⼀个SQL较为复杂时,第⼀个想到的就是原⽣的SQL语句。
SpringDataJpa使⽤原⽣sql(EntityManager)动态拼接,分页查询SpringDataJpaSpring Data JPA是较⼤的Spring Data系列的⼀部分,可轻松实现基于JPA的存储库。
该模块处理对基于JPA的数据访问层的增强⽀持。
它使构建使⽤数据访问技术的Spring⽀持的应⽤程序变得更加容易。
实现应⽤程序的数据访问层已经很长⼀段时间了。
为了执⾏简单查询以及执⾏分页和审核,必须编写太多样板代码。
Spring Data JPA旨在通过将⼯作量减少到实际需要的数量来显着改善数据访问层的实现。
作为开发⼈员,您将编写包括⾃定义finder⽅法在内的存储库接⼝,Spring会⾃动提供实现。
使⽤EntityManager 来创建原⽣查询语句在service层的代码:@PersistenceContextEntityManager entityManager;@Overridepublic Object findMeetingSignRecoredPage(Long meetingId, Integer pageIndex, Integer pageSize) {MeenoAssert.notNull(meetingId, ErrEnum.MEETING_ID_IS_EMPTY);Meeting meeting = this.meetingRepository.getOne(meetingId);MeenoAssert.notNull(meeting,ErrEnum.MEETING_IS_NOT_EXIST);Pageable pageable = PageUtils.getPageable(pageIndex,pageSize);StringBuilder sql = new StringBuilder();sql.append(" select ,MAX(r.sign) from mnt_emp_rel_meeting as e ");sql.append(" left join mnt_sign_record as r on(r.employee_id=e.employee_id) ");sql.append(" left join mnt_employee as ep on(ep.id = e.employee_id) ");sql.append(" where e.meeting_id = ? ");sql.append(" order by r.sign desc,r.create_date asc ");Query query = entityManager.createNativeQuery(sql.toString());query.setFirstResult(pageable.getOffset());query.setMaxResults(pageable.getPageSize());query.setParameter(1,meetingId);List<Object[]> list = query.getResultList();List<SignRecordView> listView = Lists.newArrayList();if(list != null && !list.isEmpty()){for (Object[] objects : list) {String empName = objects[0]==null?null:objects[0].toString();Integer sign = objects[1]==null?Constants.SIGN_RECORD_NO:Integer.parseInt(objects[1].toString());SignRecordView view = new SignRecordView();view.setEmployeeName(empName);view.setSign(sign);listView.add(view);}}//countStringBuilder countSql = new StringBuilder();countSql.append(" select count(distinct e.id) from mnt_emp_rel_meeting as e ");countSql.append(" left join mnt_sign_record as r on(r.employee_id=e.employee_id) ");countSql.append(" left join mnt_employee as ep on(ep.id = e.employee_id) ");countSql.append(" where e.meeting_id = ? ");countSql.append(" order by r.sign desc,r.create_date asc ");Query countQuery = entityManager.createNativeQuery(countSql.toString());countQuery.setParameter(1,meetingId);Object singleResult = countQuery.getResultList().get(0);Integer count = singleResult==null?0:Integer.valueOf(singleResult.toString());Map<String, Object> resultPage = PageUtils.getResultPage(count, listView);return resultPage;}PageUtils⼯具类代码如下:package com.meeno.framework.page.utils;import mon.collect.Lists;import mon.collect.Maps;import lombok.Data;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Map;/*** @description: 分页⼯具类* @author: Wzq* @create: 2019-12-26 20:19*/@Datapublic class PageUtils {/***@Description 获取集合分页对象*@Param [list, pageIndex, pageSize]*@Return void*@Author Wzq*@Date 2020/1/6*@Time 14:07*/public static <T> Map<String,Object> getCollectionPage(List<T> list, Pageable pageable){ if(list==null||list.isEmpty()){return PageUtils.getResultPage(0,null );}int offset = pageable.getOffset();int pageSize = pageable.getPageSize();List<T> listView = Lists.newArrayList();if(list!=null && !list.isEmpty()){if(list.size() < offset){return PageUtils.getResultPage(0,null );}for(;list.size() > offset && pageSize != 0 ; offset++,pageSize--){listView.add(list.get(offset));}return PageUtils.getResultPage(list.size(),listView);}return PageUtils.getResultPage(0,null );}/***@Description 根据pageIndex和pageSize获取Pageable*@Param [pageIndex, pageSize]*@Return org.springframework.data.domain.Pageable*@Author Wzq*@Date 2019/12/27*@Time 11:12*/public static Pageable getPageable(Integer pageIndex, Integer pageSize){if(pageIndex==null){pageIndex = 0;}else{pageIndex--;}if(pageSize==null){pageSize = 10;}PageRequest pageRequest = new PageRequest(pageIndex, pageSize);return pageRequest;}/***@Description 获取分页返回对象*@Param [totalCount, list]*@Return java.util.Map<ng.String,ng.Object>*@Author Wzq*@Date 2019/12/26*@Time 20:22*/public static Map<String,Object> getResultPage(Page<?> page, List<?> list){ Map<String,Object> resultPageMap = Maps.newHashMap();resultPageMap.put("totalCount",page.getTotalElements());resultPageMap.put("list",list);return resultPageMap;}public static Map<String,Object> getResultPage(Integer count, List<?> list){ Map<String,Object> resultPageMap = Maps.newHashMap();resultPageMap.put("totalCount",count);resultPageMap.put("list",list);return resultPageMap;}}。
entity framework core的查询语法Entity Framework Core(简称EF Core)是一个.NET平台上的开源ORM(对象关系映射)框架,它为开发人员提供了一种简单且灵活的方式来访问和操作数据库。
除了支持传统的LINQ查询语法外,EF Core还提供了一套查询语法来满足不同的数据操作需求。
本文将介绍EF Core的查询语法以及如何使用它来进行数据查询。
一、EF Core简介Entity Framework Core是微软推出的Entity Framework的最新版本,它是一个轻量级、跨平台的ORM框架。
相比于之前的版本,EF Core具有更好的性能、更少的依赖以及更强大的兼容性。
它支持多种数据库引擎,如SQL Server、MySQL、SQLite等,并且可以在.NET Core、.NET Framework和Mono等平台上运行。
二、EF Core查询语法1. LINQ查询语法EF Core支持使用LINQ(Language Integrated Query)进行数据查询。
LINQ是一种结合了丰富查询功能的强类型查询语言,它通过表达式树将查询转换成可执行的SQL语句。
下面是使用LINQ查询语法查询Person表中年龄大于18的记录的示例代码:```csharpusing (var context = new MyDbContext())var query = from p in context.Personswhere p.Age > 18select p;var result = query.ToList();}```在上述代码中,通过使用`from`和`where`关键字来指定查询的表和条件,并使用`select`关键字来选择需要返回的数据。
2. Lambda表达式查询除了LINQ查询语法,EF Core还支持使用Lambda表达式进行数据查询。
Lambda表达式是一种更为简洁的语法形式,可以进一步简化查询的编写,如下所示:```csharpusing (var context = new MyDbContext()){var result = context.Persons.Where(p => p.Age > 18).ToList();```通过使用`.`操作符将各种查询条件串联在一起,可以实现更加灵活的查询。
EntityFramework⽤法和常见问题优化建议1. 尽可能把操作放在server端(数据库)2. 把数据获取到client端(应⽤程序)时,只选择所需的字段。
如select,减少内存的使⽤,增加性能PredicatePredicate就是linq的⼀个Expression对象,代表⼀个检索条件,返回值为bool值,true代表获取记录,false则不获取。
使⽤And和Or⽅法把多个查询串联,判断机制为从左到右,串联后两者合并为⼀个检索结果,再继续和其他语句串联除了直接串联⼀个返回值为bool值得表达式,还可以串联另⼀个Predicate对象创建:传⼊⼀个初始bool值,代表默认检索调试,即初始返回值。
如⽆其他串联语句,当初始值为true时,相当于获取所有记录,为false 时,相当于获取空记录var predicate = PredicateBuilder.New<T>(true);Linq多表联查和分页根据筛选字段所在的表,先各⾃进⾏条件筛选,并根据主表做分页,最后再⽤join关键字联合查询var subpackageQuery = _subpackageRepository.GetAll().Where(s => s.IsDeal.Equals(1)).PageBy(input);var tranQuery = Repository.GetAll();var query = from subpackage in subpackageQueryjoin tran in tranQuery on subpackage.TranId equals tran.Idselect new GetTranDto{VarietyName = subpackage.VarietyName,BuyerName = tran.BuyerName,TranDate = subpackage.TranDate};多表联查join后再group:join后先select,然后再group,若直接group,不仅容易出错,⽽且需使⽤两次into,代码繁乱,不易理解// 坏例⼦query = from entrance in queryjoin access in _internalAccessRepository.GetAll() on entrance equals access.Xgh into joinAccessfrom j2 in joinAccess.DefaultIfEmpty()group j2 by j2.Department into groupedselect new WelcomeStatisticItem{DepartmentName = grouped.Key,RegistedCount = grouped.Count()};// 好例⼦selectQuery = from entrance in _entranceRegRepository.GetAll()join access in _internalAccessRepository.GetAll() on entrance equals access.Xghselect new{Xgh = entrance,Department = access.Department};groupQuery = from entrance in querygroup entrance by entrance.Department into groupedselect new WelcomeStatisticItem{DepartmentName = grouped.Key,RegistedCount = grouped.Count()};常见问题The LINQ expression could not be translated所写的linq表达式⽆法转化为SQL语句,⼀般原因是在linq中调⽤了本地(client)的⽅法,从⽽使得在数据库端(Server)⽆法完成调⽤Client side XXX is not supportedXXX操作不⽀持在Client端执⾏,可在XX操作之后加上select操作来解决Missing type map configuration or unsupported mapping把Dto中的AutoMapFrom特性改为AutoMap使⽤MySQL8时可能会遇到Tls版本不⼀致,⽆法连接的问题更新后⽆法及时获取在⼀个请求中,如果使⽤Repository.Update⽅法更新实体记录,再⽤Repository.Get获取实体,获取的数据是未更新前的记录。