feat: migrate snowflake ids and refresh migrations

This commit is contained in:
2025-12-02 09:04:37 +08:00
parent 462e15abbb
commit 148475fa43
174 changed files with 8020 additions and 34278 deletions

View File

@@ -3,15 +3,20 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using TakeoutSaaS.Shared.Abstractions.Entities;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Ids;
namespace TakeoutSaaS.Infrastructure.Common.Persistence;
/// <summary>
/// 应用基础 DbContext统一处理审计字段、软删除与全局查询过滤。
/// </summary>
public abstract class AppDbContext(DbContextOptions options, ICurrentUserAccessor? currentUserAccessor = null) : DbContext(options)
public abstract class AppDbContext(
DbContextOptions options,
ICurrentUserAccessor? currentUserAccessor = null,
IIdGenerator? idGenerator = null) : DbContext(options)
{
private readonly ICurrentUserAccessor? _currentUserAccessor = currentUserAccessor;
private readonly IIdGenerator? _idGenerator = idGenerator;
/// <summary>
/// 构建模型时应用软删除过滤器。
@@ -50,10 +55,35 @@ public abstract class AppDbContext(DbContextOptions options, ICurrentUserAccesso
/// </summary>
protected virtual void OnBeforeSaving()
{
ApplyIdGeneration();
ApplySoftDeleteMetadata();
ApplyAuditMetadata();
}
/// <summary>
/// 为新增实体生成雪花 ID。
/// </summary>
private void ApplyIdGeneration()
{
if (_idGenerator == null)
{
return;
}
foreach (var entry in ChangeTracker.Entries<EntityBase>())
{
if (entry.State != EntityState.Added)
{
continue;
}
if (entry.Entity.Id == 0)
{
entry.Entity.Id = _idGenerator.NextId();
}
}
}
/// <summary>
/// 将软删除实体的删除操作转换为设置 DeletedAt。
/// </summary>
@@ -114,10 +144,10 @@ public abstract class AppDbContext(DbContextOptions options, ICurrentUserAccesso
}
}
private Guid? GetCurrentUserIdOrNull()
private long? GetCurrentUserIdOrNull()
{
var userId = _currentUserAccessor?.UserId ?? Guid.Empty;
return userId == Guid.Empty ? null : userId;
var userId = _currentUserAccessor?.UserId ?? 0;
return userId == 0 ? null : userId;
}
/// <summary>

View File

@@ -141,12 +141,12 @@ internal abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDb
private sealed class DesignTimeTenantProvider : ITenantProvider
{
public Guid GetCurrentTenantId() => Guid.Empty;
public long GetCurrentTenantId() => 0;
}
private sealed class DesignTimeCurrentUserAccessor : ICurrentUserAccessor
{
public Guid UserId => Guid.Empty;
public long UserId => 0;
public bool IsAuthenticated => false;
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Shared.Abstractions.Entities;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
using TakeoutSaaS.Shared.Abstractions.Ids;
namespace TakeoutSaaS.Infrastructure.Common.Persistence;
@@ -12,14 +13,15 @@ namespace TakeoutSaaS.Infrastructure.Common.Persistence;
public abstract class TenantAwareDbContext(
DbContextOptions options,
ITenantProvider tenantProvider,
ICurrentUserAccessor? currentUserAccessor = null) : AppDbContext(options, currentUserAccessor)
ICurrentUserAccessor? currentUserAccessor = null,
IIdGenerator? idGenerator = null) : AppDbContext(options, currentUserAccessor, idGenerator)
{
private readonly ITenantProvider _tenantProvider = tenantProvider ?? throw new ArgumentNullException(nameof(tenantProvider));
/// <summary>
/// 当前请求租户 ID。
/// </summary>
protected Guid CurrentTenantId => _tenantProvider.GetCurrentTenantId();
protected long CurrentTenantId => _tenantProvider.GetCurrentTenantId();
/// <summary>
/// 保存前填充租户元数据并执行基础处理。
@@ -71,7 +73,7 @@ public abstract class TenantAwareDbContext(
foreach (var entry in ChangeTracker.Entries<IMultiTenantEntity>())
{
if (entry.State == EntityState.Added && entry.Entity.TenantId == Guid.Empty && tenantId != Guid.Empty)
if (entry.State == EntityState.Added && entry.Entity.TenantId == 0 && tenantId != 0)
{
entry.Entity.TenantId = tenantId;
}