using System.Xml.Linq;
using Mapster;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Volo.Abp.Application.Services;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Yi.Framework.Bbs.Application.Contracts.Dtos.Banner;
using Yi.Framework.Bbs.Domain.Entities.Forum;
using Yi.Framework.Rbac.Domain.Authorization;
using Yi.Framework.Rbac.Domain.Extensions;
using Yi.Framework.SettingManagement.Domain;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Abp.Application.Services
{
///
/// 常用魔改及扩展示例
///
public class TestService : ApplicationService
{
///
/// 属性注入
/// 不推荐,坑太多,容易把自己玩死,简单的东西可以用一用
///
public ISqlSugarRepository sqlSugarRepository { get; set; }
///
/// 动态Api
///
///
///
[HttpGet("hello-world")]
public string GetHelloWorld(string? name)
{
//会自动添加前缀,而不是重置,更符合习惯
//如果需要重置以"/"根目录开头即可
//你好世界
return name ?? "HelloWord";
}
///
/// 异常处理
///
///
[HttpGet("error")]
public string GetError()
{
throw new UserFriendlyException("业务异常");
throw new Exception("系统异常");
}
///
/// SqlSugar
///
///
public async Task GetSqlSugarDbAsync()
{
//用户体验优先,可直接使用Db操作,依赖抽象
return await sqlSugarRepository._DbQueryable.ToListAsync();
}
///
/// 工作单元
///
///
public async Task GetUowAsync()
{
//魔改
// 用户体验优先,万金油模式,支持高并发。支持单、多线程并发安全,支持多线程工作单元,支持。。。
// 不支持多线程无工作单元,应由工作单元统一管理(来自abp工作单元设计)
// 请注意,如果requiresNew: true只有在没有工作单元内使用,嵌套子工作单元,默认值false即可
// 自动在各个情况处理db客户端最优解之一
int i = 3;
List tasks = new List();
await sqlSugarRepository.GetListAsync();
await sqlSugarRepository.GetListAsync();
while (i > 0)
{
tasks.Add(Task.Run(async () =>
{
//以下操作是错误的,不允许在新线程中,直接操作db,所有db操作应放在工作单元内,应由工作单元统一管理-来自abp工作单元设计
//await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入2" });
using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true))
{
await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入1" });
await uow.CompleteAsync();
}
}));
await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入3" });
i--;
}
await Task.WhenAll(tasks);
}
///
/// 当前用户
///
///
public void GetCurrentUser()
{
//当token鉴权之后,可以直接获取
if (CurrentUser.Id is not null)
{
//权限
CurrentUser.GetPermissions();
//角色信息
CurrentUser.GetRoleInfo();
//部门id
CurrentUser.GetDeptId();
}
}
///
/// 数据权限
///
public void GetDataFilter()
{
//这里会数据权限过滤
using (DataFilter.DisablePermissionHandler())
{
//这里不会数据权限过滤
}
//这里会数据权限过滤
}
///
/// 对象映射
///
public void GetMapper()
{
//直接无脑Adapt,无需配置
var entity = new BannerAggregateRoot();
var dto = entity.Adapt();
}
private static int RequestNumber { get; set; } = 0;
///
/// 速率限制
///
///
// [DisableRateLimiting]
//[EnableRateLimiting("sliding")]
public int GetRateLimiting()
{
RequestNumber++;
return RequestNumber;
}
public ISettingProvider _settingProvider { get; set; }
public ISettingManager _settingManager { get; set; }
///
/// 系统配置模块
///
///
public async Task GetSettingAsync()
{
//DDD需要提前定义
//默认来说,不提供修改操作,配置应该独立
var enableOrNull = await _settingProvider.GetOrNullAsync("DDD");
//如果要进行修改,可使用yi.framework下的ISettingManager
await _settingManager.SetGlobalAsync("DDD", "false");
var enableOrNull2 = await _settingManager.GetOrNullGlobalAsync("DDD");
//当然,他的独特地方,是支持来自多个模块,例如配置文件?
var result = await _settingManager.GetOrNullConfigurationAsync("Test");
return result ?? string.Empty;
}
///
/// 分布式送abp版本:abp套了一层娃。但是纯粹鸡肋,不建议使用这个
///
public IAbpDistributedLock AbpDistributedLock { get; set; }
///
/// 分布式锁推荐使用版本:yyds,分布式锁永远的神!
///
public IDistributedLockProvider DistributedLock { get; set; }
///
/// 分布式锁
///
/// 强烈吐槽一下abp,正如他们所说,abp的分布式锁单纯为了自己用,一切还是以DistributedLock为主 >
///
public async Task GetDistributedLockAsync()
{
var number = 0;
await Parallel.ForAsync(0, 100, async (i, cancellationToken) =>
{
await using (await DistributedLock.AcquireLockAsync("MyLockName"))
{
//执行1秒
number += 1;
}
});
var number2 = 0;
await Parallel.ForAsync(0, 100, async (i, cancellationToken) =>
{
//执行1秒
number2 += 1;
});
return $"加锁结果:{number},不加锁结果:{number2}";
}
public ICurrentTenant CurrentTenant { get; set; }
public IRepository repository { get; set; }
///
/// 多租户
///
///
public async Task GetMultiTenantAsync()
{
using (var uow=UnitOfWorkManager.Begin())
{
//此处会实例化一个db,连接默认库
var defautTenantData1= await repository.GetListAsync();
using (CurrentTenant.Change(null,"Default"))
{
var defautTenantData2= await repository.GetListAsync();
await repository.InsertAsync(new BannerAggregateRoot
{
Name = "default",
});
var defautTenantData3= await repository.GetListAsync(x=>x.Name=="default");
}
//此处会实例化一个新的db连接MES
using (CurrentTenant.Change(null,"Mes"))
{
var otherTenantData1= await repository.GetListAsync();
await repository.InsertAsync(new BannerAggregateRoot
{
Name = "Mes1",
});
var otherTenantData2= await repository.GetListAsync(x=>x.Name=="Mes1");
}
//此处会复用Mesdb,不会实例化新的db
using (CurrentTenant.Change(Guid.Parse("33333333-3d72-4339-9adc-845151f8ada0")))
{
var otherTenantData1= await repository.GetListAsync();
await repository.InsertAsync(new BannerAggregateRoot
{
Name = "Mes2",
});
var otherTenantData2= await repository.GetListAsync(x=>x.Name=="Mes2");
}
//此处会将多库进行一起提交,前面的操作有报错,全部回滚
await uow.CompleteAsync();
return "根据租户切换不同的数据库,并管理db实例连接,涉及多库事务统一到最后提交";
}
}
}
}