This commit is contained in:
2026-04-22 22:37:31 +04:30
parent 15d11122b8
commit 6d35ef772c
8 changed files with 45 additions and 16 deletions
@@ -6,6 +6,11 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.HierarchyId" Version="8.0.26" />
<PackageReference Include="Microsoft.SqlServer.Types" Version="170.1000.7" />
</ItemGroup>
<ItemGroup> <ItemGroup>
@@ -35,7 +35,11 @@ internal class CategoryConfiguration : BaseEntityConfiguration<Category,Category
builder.Property(x => x.Path) builder.Property(x => x.Path)
.HasField("_path") .HasField("_path")
.IsRequired() .IsRequired()
.HasConversion(x => x.Value, x => Domain.Products.ValuesObjects.CategoryPath.CreateNew(x)) .HasConversion(
// Convert CategoryPath → HierarchyId
categoryPath => HierarchyId.Parse(categoryPath.Value),
// Convert HierarchyId → CategoryPath
hierarchyId => CategoryPath.CreateNew(hierarchyId.ToString()))
.HasColumnType("HIERARCHYID"); .HasColumnType("HIERARCHYID");
+1 -1
View File
@@ -26,7 +26,7 @@ public class ShopStartup
{ {
services.AddDbContext<ShopDbContext>(op => services.AddDbContext<ShopDbContext>(op =>
{ {
op.UseSqlServer(connectionString); op.UseSqlServer(connectionString, sqlOption=> sqlOption.UseHierarchyId());
}); });
services.AddScoped<DbContext>(sp => sp.GetRequiredService<ShopDbContext>()); services.AddScoped<DbContext>(sp => sp.GetRequiredService<ShopDbContext>());
services.AddScoped<IShopModule, ShopModule>(); services.AddScoped<IShopModule, ShopModule>();
@@ -1,4 +1,5 @@
using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; using Microsoft.EntityFrameworkCore;
using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad;
using Vizhvizh.GoldGallery.ApplicationContract.Commands; using Vizhvizh.GoldGallery.ApplicationContract.Commands;
using Vizhvizh.GoldGallery.Domain.Products.Entities; using Vizhvizh.GoldGallery.Domain.Products.Entities;
using Vizhvizh.GoldGallery.Domain.Products.Repositories; using Vizhvizh.GoldGallery.Domain.Products.Repositories;
@@ -10,10 +11,24 @@ public class CreateCategoryCommandHandler(ICategoryRepository categoryRepository
{ {
public async Task Handle(CreateCategoryCommand request, CancellationToken cancellationToken) public async Task Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
{ {
CategoryPath? parentPath = null;
if(request.ParentId != null)
{
parentPath = await categoryRepository.GetQueryAsNoTracking()
.Where(x => x.Id == request.ParentId)
.Select(x => x.Path)
.FirstOrDefaultAsync(cancellationToken);
}
var category = Category.CreateNew(request.Title, var category = Category.CreateNew(request.Title,
request.Description, request.Description,
request.Image, CategoryPath.CreateNew("/1/")); request.Image,
request.ParentId);
await categoryRepository.AddAsync(category, cancellationToken); await categoryRepository.AddAsync(category, cancellationToken);
category.SetPath(parentPath);
} }
} }
@@ -28,24 +28,20 @@ public class Category : Entity<CategoryId>
private Category(TitleVO title, private Category(TitleVO title,
DescriptionVO description, DescriptionVO description,
CategoryImage image, CategoryImage image,
CategoryPath path,
CategoryId? parentId = null) CategoryId? parentId = null)
{ {
_title = title; _title = title;
_description = description; _description = description;
_image = image; _image = image;
_parentId = parentId; _parentId = parentId;
_path = path;
} }
public static Category CreateNew(TitleVO title, public static Category CreateNew(TitleVO title,
DescriptionVO description, DescriptionVO description,
CategoryImage image, CategoryImage image,
CategoryPath path,
CategoryId? parentId = null) CategoryId? parentId = null)
{ {
return new Category(title, description, image, path, parentId); return new Category(title, description, image, parentId);
} }
public TitleVO Title => _title; public TitleVO Title => _title;
@@ -55,5 +51,9 @@ public class Category : Entity<CategoryId>
public CategoryPath Path => _path; public CategoryPath Path => _path;
public IReadOnlyList<Product> Products => _products; public IReadOnlyList<Product> Products => _products;
public void SetPath(CategoryPath? parentPath)
{
_path = CategoryPath.CreatePath(parentPath, Id);
}
} }
@@ -1,4 +1,5 @@
using Vizhvizh.BuildingBlocks.Domain; using Vizhvizh.BuildingBlocks.Domain;
using Vizhvizh.GoldGallery.Domain.Products.TypeIds;
namespace Vizhvizh.GoldGallery.Domain.Products.ValuesObjects; namespace Vizhvizh.GoldGallery.Domain.Products.ValuesObjects;
@@ -10,15 +11,15 @@ public class CategoryPath : ValueObject
Value = value; Value = value;
} }
public string Value { get; private set; } public string Value { get; private set; }
public static CategoryPath CreateNew(string value) public static CategoryPath CreateNew(string value)
=> new CategoryPath(value); => new(value);
internal static CategoryPath CreatePath(CategoryPath? parentPath, CategoryId childId)
public static CategoryPath CreatePath(CategoryPath? parentPath, string childId)
{ {
if (parentPath == null) if (parentPath == null)
return new CategoryPath(childId); return new CategoryPath($"/{childId.Value}/");
return new CategoryPath($"{parentPath.Value}/{childId}"); return new CategoryPath($"{parentPath.Value}{childId.Value}/");
} }
} }
@@ -37,7 +37,11 @@ internal class CategoryConfiguration : BaseEntityConfiguration<Category, Categor
builder.Property(x => x.Path) builder.Property(x => x.Path)
.HasField("_path") .HasField("_path")
.IsRequired() .IsRequired()
.HasConversion(x => x.Value, x => Domain.Products.ValuesObjects.CategoryPath.CreateNew(x)) .HasConversion(
// Convert CategoryPath → HierarchyId
categoryPath => HierarchyId.Parse(categoryPath.Value),
// Convert HierarchyId → CategoryPath
hierarchyId => CategoryPath.CreateNew(hierarchyId.ToString()))
.HasColumnType("HIERARCHYID"); .HasColumnType("HIERARCHYID");
// ایندکس برای Path با نوع HIERARCHYID // ایندکس برای Path با نوع HIERARCHYID
@@ -28,7 +28,7 @@ public class GoldGalleryStartup
{ {
services.AddDbContext<GoldGalleryDbContext>(op => services.AddDbContext<GoldGalleryDbContext>(op =>
{ {
op.UseSqlServer(connectionString); op.UseSqlServer(connectionString, sqlOptions => sqlOptions.UseHierarchyId());
}); });
services.AddScoped<DbContext>(sp => sp.GetRequiredService<GoldGalleryDbContext>()); services.AddScoped<DbContext>(sp => sp.GetRequiredService<GoldGalleryDbContext>());
services.AddScoped<IGoldGalleryModule, GoldGalleryModule>(); services.AddScoped<IGoldGalleryModule, GoldGalleryModule>();