From 5da65d517f523bf42be6de0660861e1f1f130972 Mon Sep 17 00:00:00 2001 From: cd-bitwarden <106776772+cd-bitwarden@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:02:48 -0500 Subject: [PATCH] Adding .AsNoTracking() to Project and SecretRepository to improve performance (#7096) --- .../Repositories/ProjectRepository.cs | 15 +++++++++------ .../Repositories/SecretRepository.cs | 17 +++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs index 78d90f9525..705acfd438 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs @@ -22,6 +22,7 @@ public class ProjectRepository : Repository c.Id == id && c.DeletedDate == null) .FirstOrDefaultAsync(); return Mapper.Map(project); @@ -36,7 +37,7 @@ public class ProjectRepository : Repository p.OrganizationId == organizationId && p.DeletedDate == null).OrderBy(p => p.RevisionDate); + var query = dbContext.Project.AsNoTracking().Where(p => p.OrganizationId == organizationId && p.DeletedDate == null).OrderBy(p => p.RevisionDate); var projects = ProjectToPermissionDetails(query, userId, accessType); @@ -58,7 +59,7 @@ public class ProjectRepository : Repository p.OrganizationId == organizationId && p.DeletedDate == null); + var query = dbContext.Project.AsNoTracking().Where(p => p.OrganizationId == organizationId && p.DeletedDate == null); query = accessType switch { @@ -118,6 +119,7 @@ public class ProjectRepository : Repository p.Secrets) .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) .ToListAsync(); @@ -141,6 +143,7 @@ public class ProjectRepository : Repository s.Id == id); var accessQuery = BuildProjectAccessQuery(projectQuery, userId, accessType); @@ -153,7 +156,7 @@ public class ProjectRepository : Repository p.OrganizationId == organizationId && projectIds.Contains(p.Id)).ToListAsync(); + var results = await dbContext.Project.AsNoTracking().Where(p => p.OrganizationId == organizationId && projectIds.Contains(p.Id)).ToListAsync(); return projectIds.Count == results.Count; } @@ -166,7 +169,7 @@ public class ProjectRepository : Repository projectIds.Contains(p.Id)); + var projectsQuery = dbContext.Project.AsNoTracking().Where(p => projectIds.Contains(p.Id)); var accessQuery = BuildProjectAccessQuery(projectsQuery, userId, accessType); return await accessQuery.ToDictionaryAsync(pa => pa.Id, pa => (pa.Read, pa.Write)); @@ -177,7 +180,7 @@ public class ProjectRepository : Repository p.OrganizationId == organizationId && p.DeletedDate == null); + var query = dbContext.Project.AsNoTracking().Where(p => p.OrganizationId == organizationId && p.DeletedDate == null); query = accessType switch { @@ -193,7 +196,7 @@ public class ProjectRepository : Repository p.Id == projectId && p.DeletedDate == null); + var query = dbContext.Project.AsNoTracking().Where(p => p.Id == projectId && p.DeletedDate == null); var queryReadAccess = accessType switch { diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs index e783e45118..693798ef5a 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs @@ -25,6 +25,7 @@ public class SecretRepository : Repository c.Id == id && c.DeletedDate == null) .FirstOrDefaultAsync(); @@ -38,6 +39,7 @@ public class SecretRepository : Repository ids.Contains(c.Id) && c.DeletedDate == null) .Include(c => c.Projects) .ToListAsync(); @@ -51,6 +53,7 @@ public class SecretRepository : Repository ids.Contains(c.Id) && c.DeletedDate != null) .Include(c => c.Projects) .ToListAsync(); @@ -64,6 +67,7 @@ public class SecretRepository : Repository c.Projects) .Where(c => c.OrganizationId == organizationId && c.DeletedDate == null); @@ -88,12 +92,12 @@ public class SecretRepository : Repository c.Projects) .Where(c => c.OrganizationId == organizationId && c.DeletedDate == null) .OrderBy(s => s.RevisionDate); var secrets = SecretToPermissionDetails(query, userId, accessType); - return await secrets.ToListAsync(); } @@ -113,11 +117,11 @@ public class SecretRepository : Repository ids.Contains(s.Id) && s.OrganizationId == organizationId && s.DeletedDate != null) .Include("Projects") .OrderBy(c => c.RevisionDate) .ToListAsync(); - return Mapper.Map>(secrets); } } @@ -128,6 +132,7 @@ public class SecretRepository : Repository c.OrganizationId == organizationId && c.DeletedDate != null) .Include("Projects") .OrderBy(c => c.RevisionDate) @@ -147,11 +152,10 @@ public class SecretRepository : Repository s.Projects) + var query = dbContext.Secret.AsNoTracking().Include(s => s.Projects) .Where(s => s.Projects.Any(p => p.Id == projectId) && s.DeletedDate == null); var secrets = SecretToPermissionDetails(query, userId, accessType); - return await secrets.ToListAsync(); } @@ -307,12 +311,12 @@ public class SecretRepository : Repository s.Id == id); var query = BuildSecretAccessQuery(secret, userId, accessType); var policy = await query.FirstOrDefaultAsync(); - return policy == null ? (false, false) : (policy.Read, policy.Write); } @@ -325,6 +329,7 @@ public class SecretRepository : Repository ids.Contains(s.Id)); var accessQuery = BuildSecretAccessQuery(secrets, userId, accessType); @@ -347,7 +352,7 @@ public class SecretRepository : Repository s.OrganizationId == organizationId && s.DeletedDate == null); + var query = dbContext.Secret.AsNoTracking().Where(s => s.OrganizationId == organizationId && s.DeletedDate == null); query = accessType switch {