## 主要变更 ### Infrastructure 层重构 - `PlatformDbContext`: 构造函数改为接受泛型 `DbContextOptions`,支持派生上下文 - `TenantStore<TContext>`: 泛型化实现,支持不同的数据库上下文 - `Extensions`: 新增 `AddPlatformCore<TContext>` 扩展方法,简化服务注册 ### 依赖调整 - 移除 Npgsql.EntityFrameworkCore.PostgreSQL 直接依赖,由使用方自行决定数据库提供程序 ### CI/CD 集成 - 新增 `.gitea/workflows/publish-nuget.yml` Gitea Actions 工作流 - 新增 `push-platform-nuget.sh` 脚本,支持: - 从 git tag 自动获取版本号 - HTTP/HTTPS 双模式支持 - 独立 NuGet 配置文件 - CI/CD 友好的环境变量配置 ### 其他 - `NuGet.Config`: 新增 NuGet 配置文件 - `Fengling.Platform.Domain`: 添加 Items 文件夹占位
189 lines
7.1 KiB
C#
189 lines
7.1 KiB
C#
namespace Fengling.Platform.Infrastructure;
|
|
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
|
|
|
public class TenantStore<TContext> : ITenantStore
|
|
where TContext : PlatformDbContext
|
|
{
|
|
private readonly TContext _context;
|
|
private readonly DbSet<Tenant> _tenants;
|
|
|
|
public TenantStore(TContext context)
|
|
{
|
|
_context = context;
|
|
_tenants = context.Tenants;
|
|
}
|
|
|
|
public void Dispose() { }
|
|
|
|
public virtual Task<Tenant?> FindByIdAsync(long? tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
if (tenantId == null) return Task.FromResult<Tenant?>(null);
|
|
return _tenants.FirstOrDefaultAsync(t => t.Id == tenantId, cancellationToken);
|
|
}
|
|
|
|
public virtual Task<Tenant?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default)
|
|
{
|
|
return _tenants.FirstOrDefaultAsync(t => t.TenantCode == tenantCode, cancellationToken);
|
|
}
|
|
|
|
public virtual async Task<IList<Tenant>> GetAllAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return await _tenants.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public virtual async Task<IList<Tenant>> GetPagedAsync(int page, int pageSize, string? name = null,
|
|
string? tenantCode = null, TenantStatus? status = null, CancellationToken cancellationToken = default)
|
|
{
|
|
var query = _tenants.AsQueryable();
|
|
|
|
if (!string.IsNullOrEmpty(name))
|
|
query = query.Where(t => t.Name.Contains(name));
|
|
|
|
if (!string.IsNullOrEmpty(tenantCode))
|
|
query = query.Where(t => t.TenantCode.Contains(tenantCode));
|
|
|
|
if (status.HasValue)
|
|
query = query.Where(t => t.Status == status);
|
|
|
|
return await query
|
|
.OrderByDescending(t => t.CreatedAt)
|
|
.Skip((page - 1) * pageSize)
|
|
.Take(pageSize)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public virtual async Task<int> GetCountAsync(string? name = null, string? tenantCode = null,
|
|
TenantStatus? status = null, CancellationToken cancellationToken = default)
|
|
{
|
|
var query = _tenants.AsQueryable();
|
|
|
|
if (!string.IsNullOrEmpty(name))
|
|
query = query.Where(t => t.Name.Contains(name));
|
|
|
|
if (!string.IsNullOrEmpty(tenantCode))
|
|
query = query.Where(t => t.TenantCode.Contains(tenantCode));
|
|
|
|
if (status.HasValue)
|
|
query = query.Where(t => t.Status == status);
|
|
|
|
return await query.CountAsync(cancellationToken);
|
|
}
|
|
|
|
public virtual async Task<IdentityResult> CreateAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
{
|
|
_tenants.Add(tenant);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
public virtual async Task<IdentityResult> UpdateAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.UpdatedAt = DateTime.UtcNow;
|
|
_tenants.Update(tenant);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
public virtual async Task<IdentityResult> DeleteAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
{
|
|
_tenants.Remove(tenant);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
return IdentityResult.Success;
|
|
}
|
|
|
|
public virtual async Task<int> GetUserCountAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return await _context.Users.CountAsync(u => u.TenantInfo.TenantId == tenantId && !u.IsDeleted, cancellationToken);
|
|
}
|
|
|
|
public virtual Task<string> GetTenantCodeAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.TenantCode);
|
|
|
|
public virtual Task<string> GetNameAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.Name);
|
|
|
|
public virtual Task<string> GetContactNameAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.ContactName);
|
|
|
|
public virtual Task<string> GetContactEmailAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.ContactEmail);
|
|
|
|
public virtual Task<string?> GetContactPhoneAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.ContactPhone);
|
|
|
|
public virtual Task<int?> GetMaxUsersAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.MaxUsers);
|
|
|
|
public virtual Task<string?> GetDescriptionAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.Description);
|
|
|
|
public virtual Task<TenantStatus> GetStatusAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.Status);
|
|
|
|
public virtual Task<DateTime?> GetExpiresAtAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.ExpiresAt);
|
|
|
|
public virtual Task<DateTime> GetCreatedAtAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.CreatedAt);
|
|
|
|
public virtual Task<DateTime?> GetUpdatedAtAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(tenant.UpdatedAt);
|
|
|
|
public virtual Task SetTenantCodeAsync(Tenant tenant, string code, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.TenantCode = code;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetNameAsync(Tenant tenant, string name, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.Name = name;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetContactNameAsync(Tenant tenant, string name, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.ContactName = name;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetContactEmailAsync(Tenant tenant, string email, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.ContactEmail = email;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetContactPhoneAsync(Tenant tenant, string? phone, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.ContactPhone = phone;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetMaxUsersAsync(Tenant tenant, int? maxUsers, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.MaxUsers = maxUsers;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetDescriptionAsync(Tenant tenant, string? description, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.Description = description;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetStatusAsync(Tenant tenant, TenantStatus status, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.Status = status;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public virtual Task SetExpiresAtAsync(Tenant tenant, DateTime? expiresAt, CancellationToken cancellationToken = default)
|
|
{
|
|
tenant.ExpiresAt = expiresAt;
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|