Note, Public ve Question AppService

This commit is contained in:
Sedat Öztürk 2026-02-04 21:51:18 +03:00
parent 1f97581874
commit 2aa5e99da2
3 changed files with 71 additions and 40 deletions

View file

@ -9,7 +9,6 @@ using Erp.Platform.BlobStoring;
using Erp.Platform.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
@ -57,8 +56,13 @@ public class NoteAppService : CrudAppService<
if (stream == null)
throw new UserFriendlyException("Dosya bulunamadı");
var activities = await Repository.GetListAsync();
var fileDto = activities
// Performans: TÜM notları çekmek yerine sadece bu dosyayı içereni bul
var queryable = await Repository.GetQueryableAsync();
var notes = await AsyncExecuter.ToListAsync(
queryable.Where(a => a.FilesJson.Contains(savedFileName))
);
var fileDto = notes
.SelectMany(a => JsonSerializer.Deserialize<List<NoteFileDto>>(a.FilesJson ?? "[]"))
.FirstOrDefault(f => f.SavedFileName == savedFileName);
@ -86,35 +90,48 @@ public class NoteAppService : CrudAppService<
if (!string.IsNullOrWhiteSpace(input.EntityId))
query = query.Where(a => a.EntityId == input.EntityId);
// 2⃣ Sıralama (opsiyonel)
// 2⃣ Sıralama (database'de)
if (!string.IsNullOrWhiteSpace(input.Sorting))
query = query.OrderBy(input.Sorting);
else
query = query.OrderByDescending(a => a.CreationTime);
// 3Paging
// 3Toplam sayı (sayfalama öncesi)
var totalCount = await AsyncExecuter.CountAsync(query);
// 4⃣ Paging
var activities = await AsyncExecuter.ToListAsync(
query.Skip(input.SkipCount).Take(input.MaxResultCount)
);
// 4⃣ Kullanıcı bilgilerini al
var userIds = activities.Select(a => a.CreatorId).Distinct().ToList();
var userQueryable = await _repositoryUser.GetQueryableAsync();
var users = await userQueryable
.Where(u => userIds.Contains(u.Id))
.Select(u => new { u.Id, u.UserName })
.ToListAsync();
// 5⃣ Kullanıcı bilgilerini Dictionary ile al (N+1 önleme)
var userIds = activities.Where(a => a.CreatorId.HasValue)
.Select(a => a.CreatorId!.Value)
.Distinct()
.ToList();
var userDict = new Dictionary<Guid, string>();
if (userIds.Any())
{
var userQueryable = await _repositoryUser.GetQueryableAsync();
var users = await AsyncExecuter.ToListAsync(
userQueryable.Where(u => userIds.Contains(u.Id))
.Select(u => new { u.Id, u.UserName })
);
userDict = users.ToDictionary(u => u.Id, u => u.UserName);
}
// 5⃣ DTO map ve kullanıcı adı ekleme
// 6⃣ DTO mapping - Dictionary lookup ile hızlı
var noteDtos = activities.Select(a =>
{
var dto = ObjectMapper.Map<Note, NoteDto>(a);
dto.CreateUserName = users.FirstOrDefault(u => u.Id == a.CreatorId)?.UserName ?? "Unknown";
dto.CreateUserName = a.CreatorId.HasValue && userDict.TryGetValue(a.CreatorId.Value, out var userName)
? userName
: "Unknown";
return dto;
}).ToList();
// 6️⃣ Sonuç dön
// 7️⃣ Sonuç dön
return new PagedResultDto<NoteDto>(totalCount, noteDtos);
}

View file

@ -152,24 +152,28 @@ public class PublicAppService : PlatformAppService
return dto;
}).ToList();
// ----------- KATEGORİLER (PostCount ile) -----------
var allCategories = await _categoryRepository.GetListAsync();
var allPostQuery = await _postRepository.GetQueryableAsync();
var counts = await AsyncExecuter.ToListAsync(
allPostQuery
.Where(p => p.IsPublished)
.GroupBy(p => p.CategoryId)
.Select(g => new { g.Key, Count = g.Count() })
// ----------- KATEGORİLER (PostCount ile) - Optimize edildi -----------
var categoryQueryable = await _categoryRepository.GetQueryableAsync();
var postQueryableForCount = await _postRepository.GetQueryableAsync();
// Kategori listesi ve post sayıları tek sorguda
var categoriesWithCounts = await AsyncExecuter.ToListAsync(
from category in categoryQueryable
join post in postQueryableForCount.Where(p => p.IsPublished)
on category.Id equals post.CategoryId into postGroup
select new
{
Category = category,
PostCount = postGroup.Count()
}
);
var countDict = counts.ToDictionary(x => x.Key, x => x.Count);
var categoryDtos = ObjectMapper.Map<List<BlogCategory>, List<BlogCategoryDto>>(allCategories);
foreach (var dto in categoryDtos)
var categoryDtos = categoriesWithCounts.Select(x =>
{
dto.PostCount = countDict.GetOrDefault(dto.Id);
}
var dto = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(x.Category);
dto.PostCount = x.PostCount;
return dto;
}).ToList();
return new BlogPostAndCategoriesDto
{
@ -180,13 +184,21 @@ public class PublicAppService : PlatformAppService
private async Task<BlogPostDto> GetPostAsync(Guid id)
{
var post = await _postRepository.GetAsync(id);
var dto = ObjectMapper.Map<BlogPost, BlogPostDto>(post);
// Get category
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(
await _categoryRepository.GetAsync(post.CategoryId)
// Tek sorguda post ve category'yi çek (N+1 önleme)
var queryable = await _postRepository.GetQueryableAsync();
var categoryQueryable = await _categoryRepository.GetQueryableAsync();
var result = await AsyncExecuter.FirstOrDefaultAsync(
from post in queryable.Where(p => p.Id == id)
join category in categoryQueryable on post.CategoryId equals category.Id
select new { Post = post, Category = category }
);
if (result == null)
throw new EntityNotFoundException(typeof(BlogPost));
var dto = ObjectMapper.Map<BlogPost, BlogPostDto>(result.Post);
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(result.Category);
return dto;
}
@ -204,9 +216,13 @@ public class PublicAppService : PlatformAppService
public async Task<List<ProductDto>> GetProductListAsync()
{
var products = await _productRepository.GetListAsync();
// Performans: Sıralamayı database'de yap
var queryable = await _productRepository.GetQueryableAsync();
var products = await AsyncExecuter.ToListAsync(
queryable.OrderBy(p => p.Order)
);
return ObjectMapper.Map<List<Product>, List<ProductDto>>(products.OrderBy(p => p.Order).ToList());
return ObjectMapper.Map<List<Product>, List<ProductDto>>(products);
}
public async Task<List<PaymentMethodDto>> GetPaymentMethodListAsync()

View file

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Erp.Platform.Entities;
using Erp.Platform.Questions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;