Note, Public ve Question AppService
This commit is contained in:
parent
1f97581874
commit
2aa5e99da2
3 changed files with 71 additions and 40 deletions
|
|
@ -9,7 +9,6 @@ using Erp.Platform.BlobStoring;
|
||||||
using Erp.Platform.Entities;
|
using Erp.Platform.Entities;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
using Volo.Abp.Application.Dtos;
|
using Volo.Abp.Application.Dtos;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
|
@ -57,8 +56,13 @@ public class NoteAppService : CrudAppService<
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
throw new UserFriendlyException("Dosya bulunamadı");
|
throw new UserFriendlyException("Dosya bulunamadı");
|
||||||
|
|
||||||
var activities = await Repository.GetListAsync();
|
// Performans: TÜM notları çekmek yerine sadece bu dosyayı içereni bul
|
||||||
var fileDto = activities
|
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 ?? "[]"))
|
.SelectMany(a => JsonSerializer.Deserialize<List<NoteFileDto>>(a.FilesJson ?? "[]"))
|
||||||
.FirstOrDefault(f => f.SavedFileName == savedFileName);
|
.FirstOrDefault(f => f.SavedFileName == savedFileName);
|
||||||
|
|
||||||
|
|
@ -86,35 +90,48 @@ public class NoteAppService : CrudAppService<
|
||||||
if (!string.IsNullOrWhiteSpace(input.EntityId))
|
if (!string.IsNullOrWhiteSpace(input.EntityId))
|
||||||
query = query.Where(a => a.EntityId == input.EntityId);
|
query = query.Where(a => a.EntityId == input.EntityId);
|
||||||
|
|
||||||
// 2️⃣ Sıralama (opsiyonel)
|
// 2️⃣ Sıralama (database'de)
|
||||||
if (!string.IsNullOrWhiteSpace(input.Sorting))
|
if (!string.IsNullOrWhiteSpace(input.Sorting))
|
||||||
query = query.OrderBy(input.Sorting);
|
query = query.OrderBy(input.Sorting);
|
||||||
else
|
else
|
||||||
query = query.OrderByDescending(a => a.CreationTime);
|
query = query.OrderByDescending(a => a.CreationTime);
|
||||||
|
|
||||||
// 3️⃣ Paging
|
// 3️⃣ Toplam sayı (sayfalama öncesi)
|
||||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
var totalCount = await AsyncExecuter.CountAsync(query);
|
||||||
|
|
||||||
|
// 4️⃣ Paging
|
||||||
var activities = await AsyncExecuter.ToListAsync(
|
var activities = await AsyncExecuter.ToListAsync(
|
||||||
query.Skip(input.SkipCount).Take(input.MaxResultCount)
|
query.Skip(input.SkipCount).Take(input.MaxResultCount)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4️⃣ Kullanıcı bilgilerini al
|
// 5️⃣ Kullanıcı bilgilerini Dictionary ile al (N+1 önleme)
|
||||||
var userIds = activities.Select(a => a.CreatorId).Distinct().ToList();
|
var userIds = activities.Where(a => a.CreatorId.HasValue)
|
||||||
var userQueryable = await _repositoryUser.GetQueryableAsync();
|
.Select(a => a.CreatorId!.Value)
|
||||||
var users = await userQueryable
|
.Distinct()
|
||||||
.Where(u => userIds.Contains(u.Id))
|
.ToList();
|
||||||
.Select(u => new { u.Id, u.UserName })
|
|
||||||
.ToListAsync();
|
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 noteDtos = activities.Select(a =>
|
||||||
{
|
{
|
||||||
var dto = ObjectMapper.Map<Note, NoteDto>(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;
|
return dto;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// 6️⃣ Sonuç dön
|
// 7️⃣ Sonuç dön
|
||||||
return new PagedResultDto<NoteDto>(totalCount, noteDtos);
|
return new PagedResultDto<NoteDto>(totalCount, noteDtos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,24 +152,28 @@ public class PublicAppService : PlatformAppService
|
||||||
return dto;
|
return dto;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// ----------- KATEGORİLER (PostCount ile) -----------
|
// ----------- KATEGORİLER (PostCount ile) - Optimize edildi -----------
|
||||||
var allCategories = await _categoryRepository.GetListAsync();
|
var categoryQueryable = await _categoryRepository.GetQueryableAsync();
|
||||||
|
var postQueryableForCount = await _postRepository.GetQueryableAsync();
|
||||||
var allPostQuery = await _postRepository.GetQueryableAsync();
|
|
||||||
var counts = await AsyncExecuter.ToListAsync(
|
// Kategori listesi ve post sayıları tek sorguda
|
||||||
allPostQuery
|
var categoriesWithCounts = await AsyncExecuter.ToListAsync(
|
||||||
.Where(p => p.IsPublished)
|
from category in categoryQueryable
|
||||||
.GroupBy(p => p.CategoryId)
|
join post in postQueryableForCount.Where(p => p.IsPublished)
|
||||||
.Select(g => new { g.Key, Count = g.Count() })
|
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 = categoriesWithCounts.Select(x =>
|
||||||
|
|
||||||
var categoryDtos = ObjectMapper.Map<List<BlogCategory>, List<BlogCategoryDto>>(allCategories);
|
|
||||||
foreach (var dto in categoryDtos)
|
|
||||||
{
|
{
|
||||||
dto.PostCount = countDict.GetOrDefault(dto.Id);
|
var dto = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(x.Category);
|
||||||
}
|
dto.PostCount = x.PostCount;
|
||||||
|
return dto;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
return new BlogPostAndCategoriesDto
|
return new BlogPostAndCategoriesDto
|
||||||
{
|
{
|
||||||
|
|
@ -180,13 +184,21 @@ public class PublicAppService : PlatformAppService
|
||||||
|
|
||||||
private async Task<BlogPostDto> GetPostAsync(Guid id)
|
private async Task<BlogPostDto> GetPostAsync(Guid id)
|
||||||
{
|
{
|
||||||
var post = await _postRepository.GetAsync(id);
|
// Tek sorguda post ve category'yi çek (N+1 önleme)
|
||||||
var dto = ObjectMapper.Map<BlogPost, BlogPostDto>(post);
|
var queryable = await _postRepository.GetQueryableAsync();
|
||||||
|
var categoryQueryable = await _categoryRepository.GetQueryableAsync();
|
||||||
// Get category
|
|
||||||
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(
|
var result = await AsyncExecuter.FirstOrDefaultAsync(
|
||||||
await _categoryRepository.GetAsync(post.CategoryId)
|
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;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
@ -204,9 +216,13 @@ public class PublicAppService : PlatformAppService
|
||||||
|
|
||||||
public async Task<List<ProductDto>> GetProductListAsync()
|
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()
|
public async Task<List<PaymentMethodDto>> GetPaymentMethodListAsync()
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Erp.Platform.Entities;
|
using Erp.Platform.Entities;
|
||||||
using Erp.Platform.Questions;
|
using Erp.Platform.Questions;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Volo.Abp.Application.Dtos;
|
using Volo.Abp.Application.Dtos;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue