Browse Source

Add batch retrieval for IdentityLinkUser entities

pull/23929/head
maliming 6 months ago
parent
commit
7e76587f60
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 4
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs
  2. 72
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserManager.cs
  3. 22
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs
  4. 21
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs

4
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs

@ -18,6 +18,10 @@ public interface IIdentityLinkUserRepository : IBasicRepository<IdentityLinkUser
List<IdentityLinkUserInfo> excludes = null,
CancellationToken cancellationToken = default);
Task<List<IdentityLinkUser>> GetListAsync(
int batchSize,
CancellationToken cancellationToken = default);
Task DeleteAsync(
IdentityLinkUserInfo linkUserInfo,
CancellationToken cancellationToken = default);

72
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserManager.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
@ -23,52 +23,64 @@ public class IdentityLinkUserManager : DomainService
CurrentTenant = currentTenant;
}
public async Task<List<IdentityLinkUser>> GetListAsync(IdentityLinkUserInfo linkUserInfo, bool includeIndirect = false, CancellationToken cancellationToken = default)
public async Task<List<IdentityLinkUser>> GetListAsync(IdentityLinkUserInfo linkUserInfo, bool includeIndirect = false, int batchSize = 100 * 100, CancellationToken cancellationToken = default)
{
using (CurrentTenant.Change(null))
{
var users = await IdentityLinkUserRepository.GetListAsync(linkUserInfo, cancellationToken: cancellationToken);
if (includeIndirect == false)
if (!includeIndirect)
{
return users;
}
var userInfos = new List<IdentityLinkUserInfo>()
{
linkUserInfo
};
var allUsers = await IdentityLinkUserRepository.GetListAsync(batchSize ,cancellationToken: cancellationToken);
return await GetAllRelatedLinksAsync(allUsers, linkUserInfo);
}
}
protected virtual Task<List<IdentityLinkUser>> GetAllRelatedLinksAsync(List<IdentityLinkUser> allUsers, IdentityLinkUserInfo userInfo)
{
var visited = new HashSet<(Guid, Guid?)>();
var result = new List<IdentityLinkUser>();
var queue = new Queue<(Guid, Guid?)>();
queue.Enqueue((userInfo.UserId, userInfo.TenantId));
visited.Add((userInfo.UserId, userInfo.TenantId));
while (queue.Count > 0)
{
var (currentUserId, currentTenantId) = queue.Dequeue();
var allUsers = new List<IdentityLinkUser>();
allUsers.AddRange(users);
var relatedLinks = allUsers.Where(x =>
(x.SourceUserId == currentUserId && x.SourceTenantId == currentTenantId) ||
(x.TargetUserId == currentUserId && x.TargetTenantId == currentTenantId)
).ToList();
do
foreach (var link in relatedLinks)
{
var nextUsers = new List<IdentityLinkUserInfo>();
foreach (var user in users)
var node1 = (link.SourceUserId, link.SourceTenantId);
var node2 = (link.TargetUserId, link.TargetTenantId);
if (!result.Contains(link))
{
if (userInfos.Any(x => x.TenantId != user.SourceTenantId || x.UserId != user.SourceUserId))
{
nextUsers.Add(new IdentityLinkUserInfo(user.SourceUserId, user.SourceTenantId));
}
if (userInfos.Any(x => x.TenantId != user.TargetTenantId || x.UserId != user.TargetUserId))
{
nextUsers.Add(new IdentityLinkUserInfo(user.TargetUserId, user.TargetTenantId));
}
result.Add(link);
}
users = new List<IdentityLinkUser>();
foreach (var next in nextUsers)
if (!visited.Contains(node1))
{
users.AddRange(await IdentityLinkUserRepository.GetListAsync(next, userInfos, cancellationToken));
queue.Enqueue(node1);
visited.Add(node1);
}
userInfos.AddRange(nextUsers);
allUsers.AddRange(users);
} while (users.Any());
return allUsers;
if (!visited.Contains(node2))
{
queue.Enqueue(node2);
visited.Add(node2);
}
}
}
return Task.FromResult(result);
}
public virtual async Task LinkAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser, CancellationToken cancellationToken = default)

22
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs

@ -51,6 +51,28 @@ public class EfCoreIdentityLinkUserRepository : EfCoreRepository<IIdentityDbCont
return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));
}
public virtual async Task<List<IdentityLinkUser>> GetListAsync(int batchSize, CancellationToken cancellationToken = default)
{
var result = new List<IdentityLinkUser>();
var total = await (await GetDbSetAsync()).LongCountAsync(cancellationToken);
var pages = (int)Math.Ceiling(total / (double)batchSize);
for (var page = 0; page < pages; page++)
{
var batch = await (await GetDbSetAsync())
.AsNoTracking()
.OrderBy(x => x.Id)
.Skip(page * batchSize)
.Take(batchSize)
.ToListAsync(cancellationToken);
result.AddRange(batch);
}
return result;
}
public virtual async Task DeleteAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default)
{
var linkUsers = await (await GetDbSetAsync()).AsNoTracking().Where(x =>

21
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs

@ -47,6 +47,27 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository<IAbpIdentityMon
return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken));
}
public virtual async Task<List<IdentityLinkUser>> GetListAsync(int batchSize, CancellationToken cancellationToken = default)
{
var result = new List<IdentityLinkUser>();
var total = await (await GetQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken);
var pages = (int)Math.Ceiling(total / (double)batchSize);
for (var page = 0; page < pages; page++)
{
var batch = await (await GetQueryableAsync(cancellationToken))
.OrderBy(x => x.Id)
.Skip(page * batchSize)
.Take(batchSize)
.ToListAsync(cancellationToken);
result.AddRange(batch);
}
return result;
}
public virtual async Task DeleteAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default)
{
var linkUsers = await (await GetQueryableAsync(cancellationToken)).Where(x =>

Loading…
Cancel
Save