Files
it/backend/HardwarePerformance.Infrastructure/Repositories/ProductRepository.cs

235 lines
8.5 KiB
C#
Raw Normal View History

2025-11-03 19:47:36 +08:00
using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Application.Interfaces;
using HardwarePerformance.Core.Entities;
using HardwarePerformance.Infrastructure.Data;
namespace HardwarePerformance.Infrastructure.Repositories
{
/// <summary>
/// 产品Repository实现
/// </summary>
public class ProductRepository : Repository<Product>, IProductRepository
{
public ProductRepository(AppDbContext context) : base(context)
{
}
public async Task<(IEnumerable<Product> products, int totalCount)> GetByCategoryAsync(
int categoryId,
int pageNumber = 1,
int pageSize = 20,
string sortBy = "CurrentRank",
bool ascending = true)
{
var query = _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.Where(p => p.CategoryId == categoryId);
// 排序
query = ApplySorting(query, sortBy, ascending);
var totalCount = await query.CountAsync();
var products = await query
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return (products, totalCount);
}
public async Task<Product?> GetByModelAsync(string model)
{
return await _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.FirstOrDefaultAsync(p => p.Model == model);
}
public async Task<IEnumerable<Product>> GetTopNByCategoryAsync(int categoryId, int n)
{
return await _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.Where(p => p.CategoryId == categoryId)
.OrderBy(p => p.CurrentRank)
.Take(n)
.ToListAsync();
}
public async Task<(IEnumerable<Product> products, int totalCount)> SearchAsync(
string searchTerm,
int? categoryId = null,
int pageNumber = 1,
int pageSize = 20)
{
var query = _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.Where(p =>
(string.IsNullOrEmpty(searchTerm) ||
p.Name.Contains(searchTerm) ||
p.Model.Contains(searchTerm) ||
p.Manufacturer.Contains(searchTerm)) &&
(!categoryId.HasValue || p.CategoryId == categoryId.Value));
var totalCount = await query.CountAsync();
var products = await query
.OrderBy(p => p.CurrentRank)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return (products, totalCount);
}
public async Task<(IEnumerable<Product> products, int totalCount)> FilterAsync(
int categoryId,
int? minScore = null,
int? maxScore = null,
int? minYear = null,
int? maxYear = null,
string? manufacturer = null,
int pageNumber = 1,
int pageSize = 20)
{
var query = _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.Where(p => p.CategoryId == categoryId);
// 性能分数筛选
if (minScore.HasValue)
{
query = query.Where(p => p.PerformanceScores.Any(ps => ps.Score >= minScore.Value));
}
if (maxScore.HasValue)
{
query = query.Where(p => p.PerformanceScores.Any(ps => ps.Score <= maxScore.Value));
}
// 发布年份筛选
if (minYear.HasValue)
{
query = query.Where(p => p.ReleaseDate.HasValue && p.ReleaseDate.Value.Year >= minYear.Value);
}
if (maxYear.HasValue)
{
query = query.Where(p => p.ReleaseDate.HasValue && p.ReleaseDate.Value.Year <= maxYear.Value);
}
// 品牌筛选
if (!string.IsNullOrEmpty(manufacturer))
{
query = query.Where(p => p.Manufacturer == manufacturer);
}
var totalCount = await query.CountAsync();
var products = await query
.OrderBy(p => p.CurrentRank)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return (products, totalCount);
}
public async Task<Product?> GetWithDetailsAsync(int id)
{
return await _dbSet
.Include(p => p.Category)
.Include(p => p.Specifications)
.Include(p => p.PerformanceScores)
.ThenInclude(ps => ps.DataSource)
.Include(p => p.RankingHistories
.OrderByDescending(rh => rh.RecordDate)
.Take(12)) // 最近12个月的排名历史
.FirstOrDefaultAsync(p => p.Id == id);
}
public async Task<IEnumerable<Product>> GetByIdsAsync(IEnumerable<int> productIds)
{
return await _dbSet
.Include(p => p.Category)
.Include(p => p.Specifications)
.Include(p => p.PerformanceScores)
.ThenInclude(ps => ps.DataSource)
.Where(p => productIds.Contains(p.Id))
.ToListAsync();
}
public async Task<IEnumerable<string>> GetManufacturersAsync(int? categoryId = null)
{
var query = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
return await query
.Where(p => !string.IsNullOrEmpty(p.Manufacturer))
.Select(p => p.Manufacturer)
.Distinct()
.OrderBy(m => m)
.ToListAsync();
}
public async Task<IEnumerable<RankingHistory>> GetRankingHistoryAsync(int productId, int months = 12)
{
var startDate = DateTime.UtcNow.AddMonths(-months);
return await _context.RankingHistories
.Where(rh => rh.ProductId == productId && rh.RecordDate >= startDate)
.OrderBy(rh => rh.RecordDate)
.ToListAsync();
}
public async Task<(IEnumerable<Product> products, int totalCount)> GetByManufacturerAsync(
string manufacturer,
int? categoryId = null,
int pageNumber = 1,
int pageSize = 20)
{
var query = _dbSet
.Include(p => p.Category)
.Include(p => p.PerformanceScores)
.Where(p => p.Manufacturer == manufacturer);
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
var totalCount = await query.CountAsync();
var products = await query
.OrderBy(p => p.CurrentRank)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return (products, totalCount);
}
private IQueryable<Product> ApplySorting(IQueryable<Product> query, string sortBy, bool ascending)
{
return sortBy.ToLower() switch
{
"name" => ascending ? query.OrderBy(p => p.Name) : query.OrderByDescending(p => p.Name),
"manufacturer" => ascending ? query.OrderBy(p => p.Manufacturer) : query.OrderByDescending(p => p.Manufacturer),
"releasedate" => ascending ? query.OrderBy(p => p.ReleaseDate) : query.OrderByDescending(p => p.ReleaseDate),
"currentrank" => ascending ? query.OrderBy(p => p.CurrentRank) : query.OrderByDescending(p => p.CurrentRank),
"score" => ascending ?
query.OrderBy(p => p.PerformanceScores.Any() ? p.PerformanceScores.Average(ps => ps.Score) : 0) :
query.OrderByDescending(p => p.PerformanceScores.Any() ? p.PerformanceScores.Average(ps => ps.Score) : 0),
_ => ascending ? query.OrderBy(p => p.CurrentRank) : query.OrderByDescending(p => p.CurrentRank)
};
}
}
}