abp vnext导航属性,级联查询。abp vnext 通用仓储 级联查询不到数据。abp vnext 多表查询,join 电脑版发表于:2022/7/24 22:42 **使用abp vnext的导航属性做级联查询,当然你可以使用自定义仓储,直接用原生的ef来写,也很简单方便** abp vnext自定义仓储里边可以使用GetDbContextAsync()拿到上下文对象,那直接使用原生ef几个,代码如下: ``` public async void Test() { var dbContext = await GetDbContextAsync(); var xx = dbContext.UserInfo.Include("UserDetails").ToList(); } ``` **如果想在通用仓储里边使用级联查询,可能最开始会这样用** 就是直接调用GetListAsync,里边传递一个true ``` public async Task<List<UserInfoDto>> GetListAsync() { List<UserInfo> userInfos = await _userinfoRepository.GetListAsync(true); List<UserInfoDto> result = ObjectMapper.Map<List<UserInfo>, List<UserInfoDto>>(userInfos); return result; } ``` 但是这样是查询不出来导航属性的,你需要配置一下级联查询关联的对象。感觉这样很麻烦哇,使用一个还要这样去配置一下。 ``` //默认的级联查询配置 Configure<AbpEntityOptions>(options => { options.Entity<UserInfo>(DemandOrderOptions => { DemandOrderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.UserDetails); }); }); ``` **我们可以使用封装的WithDetails或者是WithDetailsAsync方法** 当然还是推荐使用异步方法。代码如下,这个方法就封装得比较灵活了 ``` public async Task<List<UserInfoDto>> GetListAsync() { //使用通用仓储的封装的级联查询 List<UserInfo> userInfos = (await _userinfoRepository.WithDetailsAsync(a => a.UserDetails)).ToList(); List<UserInfoDto> result = ObjectMapper.Map<List<UserInfo>, List<UserInfoDto>>(userInfos); return result; } ``` 就是使用WithDetailsAsync在里边使用lamdba指定需要级联查询的实体,比如这样(a => a.UserDetails),就是关联查询出来UserDetails实体,很方便的。但是要注意一定要指定一下哦,不然不会默认把导航属性查询出来的,不是懒加载形式,而是直接不加载。 tn2>如果是要一次性关联多个表,往后面继续点就行了。 WithDetailsAsync(a => a.UserDetails, a => a.UserDetails)) ``` public async Task<List<UserInfoDto>> GetListAsync() { //使用通用仓储的封装的级联查询-关联多个表 List<UserInfo> userInfos = (await _userinfoRepository.WithDetailsAsync(a => a.UserDetails, a => a.UserDetails)).ToList(); List<UserInfoDto> result = ObjectMapper.Map<List<UserInfo>, List<UserInfoDto>>(userInfos); return result; } ``` tn2>如果是要一次性关联多个表,并且是子对象中的子对象。其实也是往下面继续点就可以了 WithDetailsAsync(a => a.UserDetails, a => a.UserDetails)) ``` _fileManagerRepository.WithDetailsAsync(a => a.UserInfo,a=>a.UserInfo.Department) ``` 只要有导航属性在,一条链路全部查询出来,直接往下级点就行了,无限套娃,要注意一下效率问题。 **这种级联查询之后如果需要用到AutoMapper需要涉及到子对象的情况可以这样配置:** ![](https://img.tnblog.net/arcimg/aojiancc/76af2a5d03fc42f181493260764cc840.png) 更多情况可以参考 https://www.tnblog.net/aojiancc/article/details/7573 tn2> 众所周知在EF 6 及以前的版本中,是支持懒加载(Lazy Loading)的,可惜在EF Core 并不支持,必须使用Include方法来支持导航属性的数据加载。不过现在EF Core的开发团队打算恢复对这一功能的支持(目前还未发布,不过可以在Github上面下载进行测试)。<br> 懒加载也可以叫做按需加载、延迟加载。可以分两方面来理解,一方面指暂时不需要该数据,不用在当前马上加载,而可以推迟到使用它时再加载 **abp vnext 中实现多表查询和join,可以直接通过通用仓储来** 代码如下: ``` public async void TestJoin() { var queryable = (from fileManager in await _fileManagerRepository.GetQueryableAsync() join fileType in await _fileTypeRepository.GetQueryableAsync() on fileManager.FileTypeId equals fileType.Id select new { fileName = fileManager.FileName, fileTypeName = fileType.FileTypeName }); var reuslt = queryable.ToList(); } ``` 这个和直接使用原生ef实现join其实是一个意思,原生ef通过上下文点出来的实体是一个DbSet: ![](https://img.tnblog.net/arcimg/aojiancc2/e8ba8602c4a04815b37363d4120f9a14.png) 而DbSet其实本身也是IQueryable,所以通过GetQueryableAsync()获取到实体的IQueryable对象当然也可以直接join了 ![](https://img.tnblog.net/arcimg/aojiancc2/3438c88930ed413eac2627f55d3d1bef.png)