feat: 增强仓储CRUD与种子配置
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TakeoutSaaS.Domain.Dictionary.Entities;
|
||||
using TakeoutSaaS.Domain.Dictionary.Enums;
|
||||
using TakeoutSaaS.Domain.Tenants.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Infrastructure.App.Options;
|
||||
@@ -142,81 +144,147 @@ public sealed class AppDataSeeder : IHostedService
|
||||
/// </summary>
|
||||
private async Task EnsureDictionarySeedsAsync(DictionaryDbContext dbContext, long? defaultTenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_options.DictionaryGroups == null || _options.DictionaryGroups.Count == 0)
|
||||
var dictionaryGroups = _options.DictionaryGroups ?? new List<DictionarySeedGroupOptions>();
|
||||
var hasDictionaryGroups = dictionaryGroups.Count > 0;
|
||||
|
||||
if (!hasDictionaryGroups)
|
||||
{
|
||||
_logger.LogInformation("AppSeed 未配置基础字典,跳过字典种子");
|
||||
}
|
||||
|
||||
if (hasDictionaryGroups)
|
||||
{
|
||||
foreach (var groupOptions in dictionaryGroups)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(groupOptions.Code) || string.IsNullOrWhiteSpace(groupOptions.Name))
|
||||
{
|
||||
_logger.LogWarning("AppSeed 跳过字典分组,Code 或 Name 为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
var tenantId = groupOptions.TenantId ?? defaultTenantId ?? 0;
|
||||
var code = groupOptions.Code.Trim();
|
||||
|
||||
var group = await dbContext.DictionaryGroups
|
||||
.IgnoreQueryFilters()
|
||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Code == code, cancellationToken);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
group = new DictionaryGroup
|
||||
{
|
||||
Id = 0,
|
||||
TenantId = tenantId,
|
||||
Code = code,
|
||||
Name = groupOptions.Name.Trim(),
|
||||
Scope = groupOptions.Scope,
|
||||
Description = groupOptions.Description?.Trim(),
|
||||
IsEnabled = groupOptions.IsEnabled
|
||||
};
|
||||
|
||||
await dbContext.DictionaryGroups.AddAsync(group, cancellationToken);
|
||||
_logger.LogInformation("AppSeed 创建字典分组 {GroupCode} (Tenant: {TenantId})", code, tenantId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var groupUpdated = false;
|
||||
|
||||
if (!string.Equals(group.Name, groupOptions.Name, StringComparison.Ordinal))
|
||||
{
|
||||
group.Name = groupOptions.Name.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(group.Description, groupOptions.Description, StringComparison.Ordinal))
|
||||
{
|
||||
group.Description = groupOptions.Description?.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.Scope != groupOptions.Scope)
|
||||
{
|
||||
group.Scope = groupOptions.Scope;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.IsEnabled != groupOptions.IsEnabled)
|
||||
{
|
||||
group.IsEnabled = groupOptions.IsEnabled;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (groupUpdated)
|
||||
{
|
||||
dbContext.DictionaryGroups.Update(group);
|
||||
}
|
||||
}
|
||||
|
||||
await UpsertDictionaryItemsAsync(dbContext, group, groupOptions.Items, tenantId, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
await EnsureSystemParametersAsync(dbContext, defaultTenantId, cancellationToken);
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保系统参数以字典形式幂等种子。
|
||||
/// </summary>
|
||||
private async Task EnsureSystemParametersAsync(DictionaryDbContext dbContext, long? defaultTenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
var systemParameters = _options.SystemParameters ?? new List<SystemParameterSeedOptions>();
|
||||
|
||||
if (systemParameters.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("AppSeed 未配置系统参数,跳过系统参数种子");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var groupOptions in _options.DictionaryGroups)
|
||||
var grouped = systemParameters
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value))
|
||||
.GroupBy(x => x.TenantId ?? defaultTenantId ?? 0);
|
||||
|
||||
if (!grouped.Any())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(groupOptions.Code) || string.IsNullOrWhiteSpace(groupOptions.Name))
|
||||
{
|
||||
_logger.LogWarning("AppSeed 跳过字典分组,Code 或 Name 为空");
|
||||
continue;
|
||||
}
|
||||
_logger.LogInformation("AppSeed 系统参数配置为空,跳过系统参数种子");
|
||||
return;
|
||||
}
|
||||
|
||||
var tenantId = groupOptions.TenantId ?? defaultTenantId ?? 0;
|
||||
var code = groupOptions.Code.Trim();
|
||||
|
||||
var group = await dbContext.DictionaryGroups
|
||||
foreach (var group in grouped)
|
||||
{
|
||||
var tenantId = group.Key;
|
||||
var dictionaryGroup = await dbContext.DictionaryGroups
|
||||
.IgnoreQueryFilters()
|
||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Code == code, cancellationToken);
|
||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Code == "system_parameters", cancellationToken);
|
||||
|
||||
if (group == null)
|
||||
if (dictionaryGroup == null)
|
||||
{
|
||||
group = new DictionaryGroup
|
||||
dictionaryGroup = new DictionaryGroup
|
||||
{
|
||||
Id = 0,
|
||||
TenantId = tenantId,
|
||||
Code = code,
|
||||
Name = groupOptions.Name.Trim(),
|
||||
Scope = groupOptions.Scope,
|
||||
Description = groupOptions.Description?.Trim(),
|
||||
IsEnabled = groupOptions.IsEnabled
|
||||
Code = "system_parameters",
|
||||
Name = "系统参数",
|
||||
Scope = tenantId == 0 ? DictionaryScope.System : DictionaryScope.Business,
|
||||
Description = "系统参数配置",
|
||||
IsEnabled = true
|
||||
};
|
||||
|
||||
await dbContext.DictionaryGroups.AddAsync(group, cancellationToken);
|
||||
_logger.LogInformation("AppSeed 创建字典分组 {GroupCode} (Tenant: {TenantId})", code, tenantId);
|
||||
await dbContext.DictionaryGroups.AddAsync(dictionaryGroup, cancellationToken);
|
||||
_logger.LogInformation("AppSeed 创建系统参数分组 (Tenant: {TenantId})", tenantId);
|
||||
}
|
||||
else
|
||||
|
||||
var seedItems = group.Select(x => new DictionarySeedItemOptions
|
||||
{
|
||||
var groupUpdated = false;
|
||||
Key = x.Key.Trim(),
|
||||
Value = x.Value.Trim(),
|
||||
Description = x.Description?.Trim(),
|
||||
SortOrder = x.SortOrder,
|
||||
IsEnabled = x.IsEnabled
|
||||
});
|
||||
|
||||
if (!string.Equals(group.Name, groupOptions.Name, StringComparison.Ordinal))
|
||||
{
|
||||
group.Name = groupOptions.Name.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(group.Description, groupOptions.Description, StringComparison.Ordinal))
|
||||
{
|
||||
group.Description = groupOptions.Description?.Trim();
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.Scope != groupOptions.Scope)
|
||||
{
|
||||
group.Scope = groupOptions.Scope;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (group.IsEnabled != groupOptions.IsEnabled)
|
||||
{
|
||||
group.IsEnabled = groupOptions.IsEnabled;
|
||||
groupUpdated = true;
|
||||
}
|
||||
|
||||
if (groupUpdated)
|
||||
{
|
||||
dbContext.DictionaryGroups.Update(group);
|
||||
}
|
||||
}
|
||||
|
||||
await UpsertDictionaryItemsAsync(dbContext, group, groupOptions.Items, tenantId, cancellationToken);
|
||||
await UpsertDictionaryItemsAsync(dbContext, dictionaryGroup, seedItems, tenantId, cancellationToken);
|
||||
}
|
||||
|
||||
await dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user