235 lines
8.5 KiB
C#
235 lines
8.5 KiB
C#
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)
|
|
};
|
|
}
|
|
}
|
|
} |