跳到主要内容

常见问题 FAQ

快速解决 FreeKitModules 开发中的常见问题

📋 目录


环境配置问题

❓ 启动时报错:Unable to find package 'xxx'

问题原因:NuGet 包未正确还原

解决方案

# 清理并重新还原
dotnet clean
dotnet restore
dotnet build

如果仍然失败,检查 NuGet 源配置:

dotnet nuget list source

❓ 端口 5001 被占用

错误信息System.IO.IOException: Failed to bind to address https://127.0.0.1:5001

解决方案 1 - 修改端口:

编辑 appsettings.json

{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"Https": {
"Url": "https://localhost:5002"
}
}
}
}

解决方案 2 - 释放端口(Windows):

# 查找占用端口的进程
netstat -ano | findstr :5001

# 终止进程(替换 PID)
taskkill /PID 12345 /F

数据库相关问题

❓ 数据库连接失败

错误信息Authentication to host 'localhost' for user 'root' using method 'caching_sha2_password' failed

解决方案

  1. 检查连接字符串appsettings.Development.json):
{
"ConnectionStrings": {
"DefaultDB": "0",
"MySql": "Data Source=localhost;Port=3306;User ID=root;Password=YourPassword;Initial Catalog=freekit;Charset=utf8mb4;SslMode=none;"
}
}
  1. 确认 MySQL 正在运行
# Docker 环境
docker ps | grep mysql

# 本地 Windows 服务
Get-Service MySQL*
  1. 检查防火墙:确保 3306(或自定义)端口开放

❓ FreeSql 表结构未自动同步

问题原因:实体未注册到 CodeFirst.SyncStructure

解决方案

Program.cs 或模块 Startup 中添加:

// 同步单个实体
fsql.CodeFirst.SyncStructure<Article>();

// 同步多个实体
fsql.CodeFirst.SyncStructure(
typeof(Article),
typeof(Comment),
typeof(User)
);

// 同步整个程序集
fsql.CodeFirst.SyncStructure(Assembly.GetExecutingAssembly().GetTypes());

注意:生产环境务必关闭自动同步:

fsql.CodeFirst.IsAutoSyncStructure = false;

❓ 数据库表已存在但字段未更新

问题原因:FreeSql 默认不修改已存在的字段

解决方案

手动删除表或使用 SQL 脚本更新:

-- 添加新字段
ALTER TABLE cms_article ADD COLUMN NewColumn VARCHAR(100);

-- 修改字段类型
ALTER TABLE cms_article MODIFY COLUMN Title VARCHAR(500);

或在开发环境使用 IsSyncStructureToLower

fsql.CodeFirst.IsSyncStructureToLower = true; // 强制同步

模块注册问题

❓ 启动时报错:Service 'xxx' is not registered

问题原因:模块注册顺序错误或缺少注册步骤

正确的模块注册顺序(必须按此顺序):

// 1. 程序集注册
List<Type> typeAssemblies = new List<Type>()
{
typeof(Program),
typeof(IApplicationService),
typeof(FreeKitModule),
typeof(CmsKitModuleStartup), // ← 确保添加了模块Startup
typeof(BasicIdentityModuleStartup)
};

containerBuilder.RegisterModule(new FreeKitModule(typeAssemblies.ToArray(), null));
containerBuilder.RegisterModule(new UnitOfWorkModule(typeAssemblies.ToArray(), null));

// 2. 服务依赖注入
services.AddModule<CmsKitModuleStartup>("module-cmskit", configuration);
services.AddModule<BasicIdentityModuleStartup>("module-basic-identity", configuration);

// 3. CAP 事件总线配置
var assemblies = new List<Assembly>
{
typeof(CmsKitModuleStartup).Assembly,
typeof(BasicIdentityModuleStartup).Assembly
};
services.AddKitCap(configuration).AddSubscriberAssembly(assemblies.ToArray());

// 4. Swagger 配置
var projectNames = new List<string>() { "FreeKit.CmsKit", "FreeKit.BasicIdentity" };
services.AddSwagger(configuration, projectNames);

检查清单

  • ✅ 步骤 1 必须在前
  • ✅ 所有模块的 Startup 类都添加到 typeAssemblies
  • ✅ AddModule 和 AddKitCap 使用相同的程序集列表

FreeSql 使用问题

❓ 查询时未过滤软删除数据

问题:查询结果包含 IsDeleted = true 的数据

解决方案

使用 IAuditBaseRepository 或手动过滤:

// 方式1:使用 IAuditBaseRepository(推荐)
var articles = await _repository.Where(x => x.Status == 1).ToListAsync();
// IsDeleted 自动过滤

// 方式2:手动过滤
var articles = await fsql.Select<Article>()
.Where(x => !x.IsDeleted)
.ToListAsync();

❓ 审计字段未自动填充

问题:CreateTime、CreateUserId 等字段为空

检查

  1. 实体是否继承 FullAuditEntity
  2. 是否使用 IAuditBaseRepository
  3. 当前用户信息是否正确获取
// 实体必须继承
public class Article : FullAuditEntity
{
// ...
}

// 使用审计仓储
private readonly IAuditBaseRepository<Article> _repository;

❓ 多租户数据未隔离

问题:查询到其他租户的数据

解决方案

  1. 实体实现 ITenant 接口:
public class Article : FullAuditEntity, ITenant
{
public Guid TenantId { get; set; }
}
  1. 配置全局过滤器:
fsql.GlobalFilter.Apply<ITenant>("TenantFilter", x => x.TenantId == currentTenantId);

CAP 事件总线问题

❓ CAP 事件未触发

常见原因

  1. 未添加订阅程序集
services.AddKitCap(configuration)
.AddSubscriberAssembly(typeof(CmsKitModuleStartup).Assembly); // ← 必须添加
  1. 订阅方法签名错误
// ❌ 错误:缺少 [CapSubscribe] 特性
public Task HandleArticleCreated(ArticleDto dto) { }

// ✅ 正确
[CapSubscribe("cms.article.created")]
public Task HandleArticleCreated(ArticleDto dto) { }
  1. 事件名称不匹配
// 发布
await _capPublisher.PublishAsync("cms.article.created", dto);

// 订阅(必须完全一致)
[CapSubscribe("cms.article.created")] // ← 确保名称相同

❓ CAP Dashboard 无法访问

检查配置

services.AddCap(options =>
{
options.UseDashboard(); // ← 启用 Dashboard
// ...
});

app.UseCapDashboard(); // ← 注册中间件

访问地址:https://localhost:5001/cap


Redis 连接问题

❓ Redis 连接失败

错误信息It was not possible to connect to the redis server(s)

解决方案

  1. 检查 Redis 是否运行
# Windows(如果使用 WSL)
wsl redis-cli ping
# 应返回 PONG

# Docker
docker ps | grep redis
  1. 检查连接字符串
{
"Redis": {
"ConnectionString": "localhost:6379,password=,defaultDatabase=0"
}
}
  1. 防火墙检查:确保 6379 端口开放

❓ 缓存数据未生效

问题:修改数据后仍返回旧数据

解决方案

手动清除缓存:

// 使用 IDistributedCache
await _cache.RemoveAsync($"Article:{articleId}");

// 使用 Redis 客户端
await _redisClient.DelAsync($"Article:{articleId}");

或使用缓存失效策略:

// 更新数据时自动清除缓存
await _repository.UpdateAsync(article);
await _cache.RemoveAsync($"Article:{article.Id}");

认证授权问题

❓ 401 Unauthorized 错误

常见原因

  1. Token 未传递
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  1. Token 过期:检查 expires_in 时间

  2. JWT 配置错误

{
"JWT": {
"SecretKey": "YourSecretKeyAtLeast32Characters!!",
"Issuer": "FreeKitModules",
"Audience": "FreeKitModules.API"
}
}

❓ 403 Forbidden 错误

问题原因:用户已认证但无权限

解决方案

  1. 检查用户角色:
SELECT * FROM identity_user_role WHERE UserId = 'xxx';
  1. 检查权限策略:
[Authorize(Policy = "随笔列表")] // ← 确保用户有此权限
  1. 使用 [AllowAnonymous] 测试:
[AllowAnonymous] // 暂时移除权限检查
public async Task<IActionResult> GetAsync() { }

性能优化问题

❓ 接口响应慢(>1s)

排查步骤

  1. 检查数据库查询
// 启用 SQL 日志
fsql.Aop.CrudBefore += (s, e) =>
{
Console.WriteLine($"SQL: {e.Sql}");
};
  1. 检查 N+1 查询
// ❌ N+1 查询
var articles = await _repository.ToListAsync();
foreach (var article in articles)
{
article.User = await _userRepository.GetAsync(article.CreateUserId); // ← 每次查询
}

// ✅ Include 预加载
var articles = await fsql.Select<Article>()
.Include(x => x.User)
.ToListAsync();
  1. 添加缓存
var cacheKey = $"HotArticles";
var articles = await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15);
return await _repository.Where(x => x.ViewHits > 1000).ToListAsync();
});

❓ 数据库索引未生效

检查索引

-- 查看表索引
EXEC sp_helpindex 'cms_article';

-- 创建缺失索引
CREATE INDEX IX_Article_CreateTime ON cms_article(CreateTime DESC);
CREATE INDEX IX_Article_AuditStatus_CreateTime ON cms_article(AuditStatus, CreateTime DESC);

参考各模块的 EntityReference.md 查看推荐索引。


🔍 仍未解决?

  1. 查看日志logs/ 目录下的详细错误日志
  2. 搜索 Issueshttps://gitee.com/your-repo/FreeKitModules/issues
  3. 提交新 Issue:提供错误日志、环境信息、复现步骤
  4. 加入讨论https://gitee.com/your-repo/FreeKitModules/discussions

最后更新: 2025年11月24日