// ============================================================================ // 【文件说明】HwPortalSearchDbContext.cs - 搜索子系统 EF Core 数据库上下文 // ============================================================================ // 这是 Entity Framework Core 的数据库上下文,专门用于搜索索引数据。 // // 【什么是 DbContext?】 // DbContext 是 EF Core 的核心类,负责: // 1. 管理数据库连接 // 2. 跟踪实体状态(新增、修改、删除) // 3. 执行 LINQ 查询并转换为 SQL // 4. 保存变更到数据库 // // 【与 SqlSugar 的区别】 // 项目中同时使用了两个 ORM: // - SqlSugar:用于业务表的 CRUD 操作(如 HwWeb, HwProductInfo) // - EF Core:用于搜索索引表(HwPortalSearchDoc) // // 为什么搜索用 EF Core? // 1. EF Core 的 LINQ 查询更强大,支持复杂查询 // 2. EF Core 的迁移工具更成熟 // 3. 搜索索引是独立的读模型,用不同的 ORM 隔离 // // 【与 Java Spring Boot 的对比】 // Java Spring Data JPA: // @Entity // @Table(name = "hw_portal_search_doc") // public class HwPortalSearchDoc { ... } // // public interface SearchDocRepository extends JpaRepository { // // JPA 自动实现 CRUD // } // // EF Core: // public class HwPortalSearchDbContext : DbContext { // public DbSet SearchDocs { get; } // } // // 两者概念相似: // - JPA 的 Repository ≈ EF Core 的 DbSet // - JPA 的 EntityManager ≈ EF Core 的 DbContext // ============================================================================ using Microsoft.EntityFrameworkCore; namespace Admin.NET.Plugin.HwPortal; /// /// 搜索子系统专用 DbContext。 /// /// 【设计原则 - 单一职责】 /// 这个 DbContext 只管理搜索相关的实体,不包含业务实体。 /// /// 好处: /// 1. 关注点分离:搜索逻辑和业务逻辑解耦 /// 2. 性能优化:可以单独配置搜索数据库连接 /// 3. 独立部署:搜索可以迁移到独立的数据库服务器 /// /// /// 【C# 语法知识点 - 继承 DbContext】 /// public class HwPortalSearchDbContext : DbContext /// /// DbContext 是 EF Core 的基类,继承后: /// 1. 可以定义 DbSet<T> 属性来映射表 /// 2. 可以重写 OnModelCreating 配置映射 /// 3. 可以重写 OnConfiguring 配置连接 /// /// 对比 Java JPA: /// Java 不需要显式继承 DbContext,而是用 @Entity 和 Repository。 /// /// public class HwPortalSearchDbContext : DbContext { /// /// 构造函数(依赖注入)。 /// /// 【C# 语法知识点 - 构造函数注入】 /// public HwPortalSearchDbContext(DbContextOptions<HwPortalSearchDbContext> options) : base(options) /// /// DbContextOptions<T> 包含数据库连接配置: /// - 连接字符串 /// - 数据库提供者(MySQL, PostgreSQL, SQLite 等) /// - 其他配置选项 /// /// : base(options) 把配置传给父类 DbContext。 /// /// 对比 Java Spring Boot: /// Java 通常用 @Autowired 注入 DataSource 或 EntityManagerFactory: /// @Autowired /// public SearchRepository(EntityManager em) { /// this.em = em; /// } /// /// C# 的构造函数注入是 DI 的标准方式。 /// /// /// 数据库上下文配置选项 public HwPortalSearchDbContext(DbContextOptions options) : base(options) { } /// /// 搜索文档表映射。 /// /// 【C# 语法知识点 - DbSet<T> 属性】 /// public DbSet<HwPortalSearchDoc> SearchDocs => Set<HwPortalSearchDoc>(); /// /// DbSet<T> 是 EF Core 的"表映射": /// - 每个 DbSet<T> 对应数据库中的一张表 /// - 可以用 LINQ 查询:_db.SearchDocs.Where(x => x.Title.Contains("关键词")) /// - 可以增删改:_db.SearchDocs.Add(doc), _db.SearchDocs.Remove(doc) /// /// => Set<HwPortalSearchDoc>() 是表达式体属性: /// - 等价于 { return Set<HwPortalSearchDoc>(); } /// - Set<T>() 是 DbContext 的方法,返回 DbSet<T> /// /// 对比 Java JPA: /// Java 的 Repository 接口类似: /// public interface SearchDocRepository extends JpaRepository { /// // JPA 自动实现 CRUD /// } /// /// C# 的 DbSet 更接近底层,但 LINQ 查询更强大。 /// /// public DbSet SearchDocs => Set(); /// /// 配置实体映射。 /// /// 【C# 语法知识点 - OnModelCreating 方法】 /// protected override void OnModelCreating(ModelBuilder modelBuilder) /// /// OnModelCreating 是 DbContext 的虚方法,用于: /// 1. 配置实体到表的映射 /// 2. 配置列类型、索引、约束 /// 3. 配置关系(一对多、多对多) /// /// ModelBuilder 是"流畅 API"(Fluent API): /// - 用链式方法调用配置映射 /// - 比 Data Annotations(特性)更灵活 /// /// 对比 Java JPA: /// Java 可以用 @Column, @Table 等注解配置: /// @Column(name = "content", columnDefinition = "LONGTEXT") /// private String content; /// /// 或者用 JPA 的 @Entity + @Table 注解。 /// /// EF Core 的 Fluent API 更强大,适合复杂配置。 /// /// /// 模型构建器 protected override void OnModelCreating(ModelBuilder modelBuilder) { // 调用父类方法(如果有基础配置)。 base.OnModelCreating(modelBuilder); // 【配置 HwPortalSearchDoc 实体】 // modelBuilder.Entity<HwPortalSearchDoc>(entity => { ... }) // 对特定实体进行详细配置。 modelBuilder.Entity(entity => { // 【列类型配置】 // entity.Property(x => x.Content).HasColumnType("longtext") // // 为什么显式指定列类型? // 1. 不同数据库提供者的默认映射不同 // - MySQL: string → VARCHAR(255) // - PostgreSQL: string → TEXT // 2. 搜索内容可能很长,需要 longtext(MySQL 的 4GB 文本类型) // 3. 显式声明避免迁移时类型变化 // // 对比 Java JPA: // Java: @Column(name = "content", columnDefinition = "LONGTEXT") entity.Property(x => x.Content).HasColumnType("longtext"); // 【JSON 列类型】 // MySQL 5.7+ 支持 JSON 类型: // - 自动验证 JSON 格式 // - 支持 JSON 函数查询(如 JSON_EXTRACT) // - 更高效的存储 entity.Property(x => x.RouteQueryJson).HasColumnType("json"); }); } }