应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

abp vnext 事务,多表查询,自定义仓储

11168人阅读 2022/7/24 17:44 总访问:5182562 评论:0 收藏:0 手机
分类: 软件架构

abp vnext 中的通用仓储主要是封装的单表操作,如果是实现事务的话最好还是封装一个自定义仓储。

自定义仓储大概的结构如下:

然后使用事务的方式和使用ef就完全一样了

我们这里是在数据库访问层用的ef

  1. /// <summary>
  2. /// 事务示例
  3. /// </summary>
  4. /// <param name="landInfo"></param>
  5. /// <param name="userInfo"></param>
  6. /// <returns></returns>
  7. public async Task<int> UpdateTrans(LandInfo landInfo, UserInfo userInfo)
  8. {
  9. var getDbContext = await GetDbContextAsync();
  10. using (var transaction = getDbContext.Database.BeginTransaction())
  11. {
  12. try
  13. {
  14. getDbContext.LandInfo.Update(landInfo);
  15. getDbContext.SaveChanges();
  16. userInfo.UserDetailsId = landInfo.Id;
  17. getDbContext.UserInfo.Add(userInfo);
  18. getDbContext.SaveChanges();
  19. transaction.Commit();
  20. return 1;
  21. }
  22. catch (Exception)
  23. {
  24. transaction.Rollback();
  25. return -1;
  26. }
  27. }
  28. }

自定义仓储下多表查询的话,也是和使用ef一样了

  1. /// <summary>
  2. /// 多表查询示例
  3. /// </summary>
  4. public async void JoinTemp()
  5. {
  6. var dbContext = await GetDbContextAsync();
  7. /*表1:UserInfo ; 表2:UserDetails ; 关联条件 UserInfo.UserDetailsId = UserDetails.Id
  8. 返回结果表1的UserName字段,表2的avatar字段
  9. */
  10. //方法1
  11. dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new {
  12. userName = a.UserName,
  13. avatar = b.avatar
  14. });
  15. //方法2:
  16. var query = from u in dbContext.UserInfo
  17. join p in dbContext.UserDetails on u.UserDetailsId equals p.Id
  18. select new
  19. {
  20. username = u.UserName,
  21. avatar = p.avatar
  22. };
  23. //方法3:直接执行sql语句返回结果
  24. }

整体点的代码贴一下

  1. using Microsoft.EntityFrameworkCore;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
  7. using Volo.Abp.EntityFrameworkCore;
  8. using WY.JBLand.Domain.Land;
  9. using WY.JBLand.Domain.User;
  10. namespace WY.JBLand.EntityFrameworkCore.Land
  11. {
  12. public class LandInfoRepository : EfCoreRepository<WyJBLandDbContext, LandInfo, int>, ILandInfoRepository
  13. {
  14. public LandInfoRepository(IDbContextProvider<WyJBLandDbContext> dbContextProvider) : base(dbContextProvider)
  15. {
  16. }
  17. /// <summary>
  18. /// 多表查询示例
  19. /// </summary>
  20. public async void JoinTemp()
  21. {
  22. var dbContext = await GetDbContextAsync();
  23. /*表1:UserInfo ; 表2:UserDetails ; 关联条件 UserInfo.UserDetailsId = UserDetails.Id
  24. 返回结果表1的UserName字段,表2的avatar字段
  25. */
  26. //方法1
  27. dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new
  28. {
  29. userName = a.UserName,
  30. avatar = b.avatar
  31. });
  32. //方法2:
  33. var query = from u in dbContext.UserInfo
  34. join p in dbContext.UserDetails on u.UserDetailsId equals p.Id
  35. select new
  36. {
  37. username = u.UserName,
  38. avatar = p.avatar
  39. };
  40. //方法3:直接执行sql语句返回结果
  41. }
  42. /// <summary>
  43. /// 事务示例
  44. /// </summary>
  45. /// <param name="landInfo"></param>
  46. /// <param name="userInfo"></param>
  47. /// <returns></returns>
  48. public async Task<int> UpdateTrans(LandInfo landInfo, UserInfo userInfo)
  49. {
  50. var getDbContext = await GetDbContextAsync();
  51. using (var transaction = getDbContext.Database.BeginTransaction())
  52. {
  53. try
  54. {
  55. getDbContext.LandInfo.Update(landInfo);
  56. getDbContext.SaveChanges();
  57. userInfo.UserDetailsId = landInfo.Id;
  58. getDbContext.UserInfo.Add(userInfo);
  59. getDbContext.SaveChanges();
  60. transaction.Commit();
  61. return 1;
  62. }
  63. catch (Exception)
  64. {
  65. transaction.Rollback();
  66. return -1;
  67. }
  68. }
  69. }
  70. public async Task<LandInfo> FindByNameAsync(string name)
  71. {
  72. var dbSet = await GetDbSetAsync();
  73. return await dbSet.FirstOrDefaultAsync(author => author.landName == name);
  74. }
  75. public async Task<List<LandInfo>> GetListAsync(int skipCount, int maxResultCount, string filter = null)
  76. {
  77. var dbSet = await GetDbSetAsync();
  78. return await dbSet
  79. .WhereIf(
  80. !filter.IsNullOrWhiteSpace(),
  81. author => author.landName.Contains(filter)
  82. )
  83. .OrderBy(a => a.Id)
  84. .Skip(skipCount)
  85. .Take(maxResultCount)
  86. .ToListAsync();
  87. }
  88. }
  89. }

当然使用通用仓储也可以实现多表查询,比如通过通用仓储拿到上下文对象后在去join,但不建议这么去使用

比如连表查询join,可以这样:

  1. public async void JoinTemp()
  2. {
  3. WyJBLandDbContext dbContext = await _landInfoRepository.GetDbContextAsync() as WyJBLandDbContext;
  4. dbContext.UserInfo.Join(dbContext.UserDetails, a => a.UserDetailsId, b => b.Id, (a, b) => new
  5. {
  6. userName = a.UserName,
  7. avatar = b.avatar
  8. });
  9. }

但是这种直接在应用层使用上下文对象的方法是不科学的,依赖性过于强了

我们建议使用的方法是通过通用仓储拿到GetQueryableAsync()后实现join

如下:

  1. public async void TestJoin()
  2. {
  3. var queryable = (from fileManager in await _fileManagerRepository.GetQueryableAsync()
  4. join fileType in await _fileTypeRepository.GetQueryableAsync() on fileManager.FileTypeId equals fileType.Id
  5. select new
  6. {
  7. fileName = fileManager.FileName,
  8. fileTypeName = fileType.FileTypeName
  9. });
  10. var reuslt = queryable.ToList();
  11. }

这个和直接使用原生ef实现join其实是一个意思,原生ef通过上下文点出来的实体是一个DbSet:

而DbSet其实本身也是IQueryable,所以通过GetQueryableAsync()获取到实体的IQueryable对象当然也可以直接join了


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

EF多种更新方法。EF修改Entity Framework修改。abp vnext ef 更新封装

[TOC] 方法1:直接执行更新的sql语句过于简单不说了 方法2:先查询在更新Users result = oapEntities.Users.Where(a =&gt...

EF添加。Entity Framework添加。abp vnext ef 添加批量添加的封装

EF的添加如下,代码比较添加: ShipEntities se = new ShipEntities(); se.Users.Add(user); se.SaveChanges(); 方法2:...

领域驱动设计DDD abp vnext 一:项目架构搭建模块使用

[TOC]用户接口层改造nuget中下载abp依赖VoLo.Abp.AspNetCore.Mvc ItemGroup添加方式 &lt;ItemGroup&gt; &lt;Packa...

abp vnext ObjectMapper 为空

abp vnext ObjectMapper 报空引用的错。System.NullReferenceException:“Object reference not set to an instance of an ...

领域驱动设计DDD abp vnext 二:使用仓储

[TOC]领域驱动设计仓储介绍在领域层和数据映射层之间进行中介,使用类似集合的接口来操作领域对象.” (Martin Fowler)。 实...

abp vnext 通用仓储操作空引用。abp vnext 仓储报错仓储为空。依赖注入报错

An internal error occurred during your request! abp vnext 通用仓储依赖注入拿到为空,或者能正常拿到依赖注入操作空引...

领域驱动设计DDD abp vnext 三:领域模型 之 失血模型贫血模型充血模型胀血模型

[TOC]领域模型分为:失血模型,贫血模型,充血模型,胀血模型。 一、失血模型传统的三层架构,实体对象就是简单的POJO或者...

abp vnext连接mysql。.net core连接mysql。ef core连接mysql

增加一个MySQL的库:Volo.Abp.EntityFrameworkCore.MySQL &lt;PackageReference Include=&quot;Volo.Abp.EntityFrameworkCo...

abp vnext ef core连接MySql报空引用错连接SqlServer报空引用错。abp vnext 的坑

使用abp vnext 真的太喜欢报空引用的错了。你报点错给一点具体的错不行么,这样搞起让人去猜太坑了,比如前面的auto_fac没...

abp vnext项目结构分析

Domain 项目领域层,领域驱动开发的核心层。 它主要包含 实体, 集合根, 领域服务, 值类型, 仓储接口 和解决方案的其他领域...

abp vnext 实体的guid主键

Guid主键的实体如果你的实体Id类型为 Guid,有一些好的实践可以实现: 创建一个构造函数,获取ID作为参数传递给基类.— 如...

abp vnext 获取配置文件

代码如下: public override void ConfigureServices(ServiceConfigurationContext context) { var services = cont...

abp vnext验证

验证DTO微软官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-7.0 数据注...

abp vnext 通用仓储 ef core。WhereIf多条件动态条件分页动态排序等

abp vnext 通用仓储 ef core WhereIf,多条件,分页等public async Task&lt;List&lt;LandInfoDto&gt;&gt; GetListAsync(Pag...

abp vnext导航属性级联查询。abp vnext 通用仓储 级联查询不到数据。abp vnext 多表查询join

使用abp vnext的导航属性做级联查询,当然你可以使用自定义仓储,直接用原生的ef来写,也很简单方便abp vnext自定义仓储里...