TNBLOG
首页
博客
视频
资源
问答
猿趣
手机
关于
搜索
收藏
便签
笔记
消息
创作
登录
剑轩
故如虹,知恩;故如月,知明
博主信息
排名
6
文章
6
粉丝
16
评论
8
文章类别
CSS
15篇
微服务
41篇
Git
14篇
.NET
102篇
移动开发
33篇
软件架构
23篇
.NET Core
119篇
.NET MVC
11篇
英语
3篇
随笔
86篇
Bootstrap
3篇
Redis
21篇
编辑器
10篇
Js相关
15篇
虚拟化
8篇
更多
Oracle
7篇
Python
14篇
数据库
26篇
EF
17篇
微信
3篇
前端
151篇
消息队列
6篇
docker
41篇
多线程
1篇
Java
4篇
软件基础
2篇
C++
2篇
WCF
7篇
Linux
7篇
nginx
5篇
K8S
9篇
ABP
2篇
最新文章
最新评价
{{item.articleTitle}}
{{item.blogName}}
:
{{item.content}}
关于我们
ICP备案 :
渝ICP备18016597号-1
网站信息:
2018-2024
TNBLOG.NET
技术交流:
群号656732739
联系我们:
contact@tnblog.net
欢迎加群
欢迎加群交流技术
原
abp vnext 事务,多表查询,自定义仓储
8610
人阅读
2022/7/24 17:44
总访问:
3983315
评论:
0
收藏:
0
手机
分类:
软件架构
[TOC] abp vnext 中的通用仓储主要是封装的单表操作,如果是实现事务的话最好还是封装一个自定义仓储。 ### 自定义仓储大概的结构如下: ![](https://img.tnblog.net/arcimg/aojiancc2/afc4ec09297847f2811c0fa4bb6d51f9.png) #### 然后使用事务的方式和使用ef就完全一样了 我们这里是在数据库访问层用的ef ``` /// <summary> /// 事务示例 /// </summary> /// <param name="landInfo"></param> /// <param name="userInfo"></param> /// <returns></returns> public async Task<int> UpdateTrans(LandInfo landInfo, UserInfo userInfo) { var getDbContext = await GetDbContextAsync(); using (var transaction = getDbContext.Database.BeginTransaction()) { try { getDbContext.LandInfo.Update(landInfo); getDbContext.SaveChanges(); userInfo.UserDetailsId = landInfo.Id; getDbContext.UserInfo.Add(userInfo); getDbContext.SaveChanges(); transaction.Commit(); return 1; } catch (Exception) { transaction.Rollback(); return -1; } } } ``` #### 自定义仓储下多表查询的话,也是和使用ef一样了 ``` /// <summary> /// 多表查询示例 /// </summary> public async void JoinTemp() { var dbContext = await GetDbContextAsync(); /*表1:UserInfo ; 表2:UserDetails ; 关联条件 UserInfo.UserDetailsId = UserDetails.Id 返回结果表1的UserName字段,表2的avatar字段 */ //方法1 dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new { userName = a.UserName, avatar = b.avatar }); //方法2: var query = from u in dbContext.UserInfo join p in dbContext.UserDetails on u.UserDetailsId equals p.Id select new { username = u.UserName, avatar = p.avatar }; //方法3:直接执行sql语句返回结果 } ``` 整体点的代码贴一下 ``` using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; using WY.JBLand.Domain.Land; using WY.JBLand.Domain.User; namespace WY.JBLand.EntityFrameworkCore.Land { public class LandInfoRepository : EfCoreRepository<WyJBLandDbContext, LandInfo, int>, ILandInfoRepository { public LandInfoRepository(IDbContextProvider<WyJBLandDbContext> dbContextProvider) : base(dbContextProvider) { } /// <summary> /// 多表查询示例 /// </summary> public async void JoinTemp() { var dbContext = await GetDbContextAsync(); /*表1:UserInfo ; 表2:UserDetails ; 关联条件 UserInfo.UserDetailsId = UserDetails.Id 返回结果表1的UserName字段,表2的avatar字段 */ //方法1 dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new { userName = a.UserName, avatar = b.avatar }); //方法2: var query = from u in dbContext.UserInfo join p in dbContext.UserDetails on u.UserDetailsId equals p.Id select new { username = u.UserName, avatar = p.avatar }; //方法3:直接执行sql语句返回结果 } /// <summary> /// 事务示例 /// </summary> /// <param name="landInfo"></param> /// <param name="userInfo"></param> /// <returns></returns> public async Task<int> UpdateTrans(LandInfo landInfo, UserInfo userInfo) { var getDbContext = await GetDbContextAsync(); using (var transaction = getDbContext.Database.BeginTransaction()) { try { getDbContext.LandInfo.Update(landInfo); getDbContext.SaveChanges(); userInfo.UserDetailsId = landInfo.Id; getDbContext.UserInfo.Add(userInfo); getDbContext.SaveChanges(); transaction.Commit(); return 1; } catch (Exception) { transaction.Rollback(); return -1; } } } public async Task<LandInfo> FindByNameAsync(string name) { var dbSet = await GetDbSetAsync(); return await dbSet.FirstOrDefaultAsync(author => author.landName == name); } public async Task<List<LandInfo>> GetListAsync(int skipCount, int maxResultCount, string filter = null) { var dbSet = await GetDbSetAsync(); return await dbSet .WhereIf( !filter.IsNullOrWhiteSpace(), author => author.landName.Contains(filter) ) .OrderBy(a => a.Id) .Skip(skipCount) .Take(maxResultCount) .ToListAsync(); } } } ``` ### 当然使用通用仓储也可以实现多表查询,比如通过通用仓储拿到上下文对象后在去join,但不建议这么去使用 比如连表查询join,可以这样: ``` public async void JoinTemp() { WyJBLandDbContext dbContext = await _landInfoRepository.GetDbContextAsync() as WyJBLandDbContext; dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new { userName = a.UserName, avatar = b.avatar }); } ``` 但是这种直接在应用层使用上下文对象的方法是不科学的,依赖性过于强了 ### 我们建议使用的方法是通过通用仓储拿到GetQueryableAsync()后实现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)
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
👈{{preArticle.title}}
👉{{nextArticle.title}}
评价
{{titleitem}}
{{titleitem}}
{{item.content}}
{{titleitem}}
{{titleitem}}
{{item.content}}