惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Project Zero
Project Zero
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Scott Helme
Scott Helme
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
WordPress大学
WordPress大学
AWS News Blog
AWS News Blog
小众软件
小众软件
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
AI
AI
美团技术团队
人人都是产品经理
人人都是产品经理
S
Secure Thoughts
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
宝玉的分享
宝玉的分享
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
大猫的无限游戏
大猫的无限游戏
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
罗磊的独立博客
Recent Announcements
Recent Announcements
H
Hacker News: Front Page
博客园 - 【当耐特】
K
Kaspersky official blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
F
Full Disclosure
Google DeepMind News
Google DeepMind News
V
V2EX
博客园 - 聂微东
量子位
云风的 BLOG
云风的 BLOG
C
Check Point Blog
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
W
WeLiveSecurity
Engineering at Meta
Engineering at Meta
V2EX - 技术
V2EX - 技术
Vercel News
Vercel News
L
LINUX DO - 热门话题
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
The GitHub Blog
The GitHub Blog

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
第二章:框架架构与核心组件
我才是银古 · 2026-06-19 · via 博客园 - 我才是银古

第二章:框架架构与核心组件

2.1 整体架构设计

2.1.1 分层架构

SOD框架采用经典的分层架构设计,从底层到顶层依次为:

┌───────────────────────────────────────────────────────────────┐
│                       表示层 (Presentation)                    │
│    ┌─────────────────┐  ┌─────────────────────────────────┐  │
│    │  PWMIS.Windows  │  │         PWMIS.Web               │  │
│    │  WinForm控件    │  │         WebForm控件              │  │
│    └─────────────────┘  └─────────────────────────────────┘  │
├───────────────────────────────────────────────────────────────┤
│                       业务逻辑层 (Business Logic)              │
│    ┌─────────────────────────────────────────────────────┐   │
│    │                    DbContext                         │   │
│    │           数据上下文(可选,用于Code First)           │   │
│    └─────────────────────────────────────────────────────┘   │
├───────────────────────────────────────────────────────────────┤
│                       数据映射层 (Data Mapping)                │
│   ┌───────────┐  ┌─────────────┐  ┌───────────────────┐     │
│   │ SQL-MAP   │  │    ORM      │  │  EntityContainer  │     │
│   │ DBMapper  │  │EntityQuery  │  │    数据容器        │     │
│   └───────────┘  └─────────────┘  └───────────────────┘     │
├───────────────────────────────────────────────────────────────┤
│                       实体层 (Entity Layer)                    │
│   ┌─────────────────────────────────────────────────────────┐│
│   │                    EntityBase                           ││
│   │    实体类基类(动态属性、元数据映射、状态追踪)           ││
│   └─────────────────────────────────────────────────────────┘│
├───────────────────────────────────────────────────────────────┤
│                    数据访问层 (Data Access Layer)              │
│   ┌─────────────────────────────────────────────────────────┐│
│   │                     AdoHelper                           ││
│   │         抽象数据访问辅助类(数据库无关的API)            ││
│   └─────────────────────────────────────────────────────────┘│
├───────────────────────────────────────────────────────────────┤
│                   数据提供程序层 (Data Provider Layer)         │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌─────────┐    │
│  │SqlServer│ │ MySQL  │ │ Oracle │ │PostgreSQL││ SQLite │    │
│  └────────┘ └────────┘ └────────┘ └────────┘ └─────────┘    │
│  ┌────────┐ ┌────────┐ ┌────────┐                           │
│  │  达梦  │ │人大金仓 │ │ Access │  ...更多数据库...          │
│  └────────┘ └────────┘ └────────┘                           │
└───────────────────────────────────────────────────────────────┘

2.1.2 核心设计模式

SOD框架运用了多种经典的设计模式:

抽象工厂模式 (Abstract Factory)

用于创建不同数据库的数据访问提供程序:

// 根据配置自动创建对应数据库的AdoHelper
AdoHelper db = MyDB.GetDBHelper();  // 自动识别数据库类型

单例模式 (Singleton)

EntityQuery采用单例模式,避免重复创建:

// 获取单例实例
var eq = EntityQuery<UserEntity>.Instance;

建造者模式 (Builder)

OQL使用链式调用的建造者模式:

var oql = OQL.From(user)
    .Select(user.ID, user.Name)  // 构建SELECT
    .Where(user.Status)          // 构建WHERE
    .OrderBy(user.ID)            // 构建ORDER BY
    .END;                        // 完成构建

策略模式 (Strategy)

不同数据库的SQL生成策略:

// 框架内部根据数据库类型选择不同的分页策略
// SqlServer: ROW_NUMBER()
// MySQL: LIMIT
// Oracle: ROWNUM
oql.Limit(10, 1);  // 自动适配不同数据库

2.2 AdoHelper:数据访问核心

2.2.1 AdoHelper的设计理念

AdoHelper是SOD框架的数据访问核心,它是一个抽象类,提供了与具体数据库无关的数据访问API。这种设计使得上层代码不需要关心底层使用的是什么数据库。

public abstract class AdoHelper
{
    // 执行非查询SQL
    public abstract int ExecuteNonQuery(string sql, CommandType cmdType, IDataParameter[] paras);
    
    // 执行查询返回DataSet
    public abstract DataSet ExecuteDataSet(string sql, CommandType cmdType, IDataParameter[] paras);
    
    // 执行查询返回DataReader
    public abstract IDataReader ExecuteReader(string sql, CommandType cmdType, IDataParameter[] paras);
    
    // 执行查询返回标量值
    public abstract object ExecuteScalar(string sql, CommandType cmdType, IDataParameter[] paras);
    
    // 获取数据库参数对象
    public abstract IDataParameter GetParameter(string name, object value);
    
    // ... 更多抽象方法
}

2.2.2 创建AdoHelper实例

SOD框架提供了多种方式创建AdoHelper实例:

// 方式1:根据连接名称创建(推荐)
AdoHelper db = MyDB.GetDBHelperByConnectionName("local");

// 方式2:使用最后一个连接配置
AdoHelper db = MyDB.GetDBHelper();

// 方式3:直接实例化具体的数据库提供程序
AdoHelper db = new SqlServer();
db.ConnectionString = "Data Source=.;Initial Catalog=MyDB;...";

// 方式4:根据配置字符串动态创建
AdoHelper db = AdoHelper.CreateHelper("local");

2.2.3 核心方法详解

ExecuteNonQuery - 执行非查询操作

// 执行INSERT/UPDATE/DELETE等操作
string sql = "UPDATE User SET Status=@Status WHERE ID=@ID";
IDataParameter[] paras = new IDataParameter[] {
    db.GetParameter("@Status", 1),
    db.GetParameter("@ID", 100)
};
int affectedRows = db.ExecuteNonQuery(sql, CommandType.Text, paras);

ExecuteDataSet - 返回数据集

// 查询返回DataSet
string sql = "SELECT * FROM User WHERE DeptId=@DeptId";
var paras = new[] { db.GetParameter("@DeptId", 1) };
DataSet ds = db.ExecuteDataSet(sql, CommandType.Text, paras);
DataTable dt = ds.Tables[0];

ExecuteScalar - 返回单个值

// 查询记录数
string sql = "SELECT COUNT(*) FROM User WHERE Status=1";
int count = Convert.ToInt32(db.ExecuteScalar(sql));

ExecuteMapper - 微型ORM映射

// 直接映射到对象列表
string sql = "SELECT ID,Name,Status FROM User WHERE DeptId={0}";
var users = db.ExecuteMapper(sql, 1)
    .MapToList(reader => new User {
        ID = reader.GetInt32(0),
        Name = reader.GetString(1),
        Status = reader.GetInt32(2)
    });

2.2.4 事务支持

// 简单事务
db.BeginTransaction();
try
{
    db.ExecuteNonQuery("INSERT INTO ...");
    db.ExecuteNonQuery("UPDATE ...");
    db.Commit();
}
catch
{
    db.Rollback();
    throw;
}

// 使用Session管理连接(推荐)
db.OpenSession();
try
{
    db.BeginTransaction();
    // 执行多个操作...
    db.Commit();
}
finally
{
    db.CloseSession();
}

2.3 EntityBase:实体类基类

2.3.1 设计思想

EntityBase是SOD框架所有实体类的基类,它实现了"充血实体类"模型,具有以下特性:

  1. 动态属性存储:属性值存储在内部字典中
  2. 状态追踪:记录哪些属性被修改过
  3. 元数据映射:动态定义表名、主键、字段映射
  4. 索引器访问:支持通过字符串名称访问属性

2.3.2 核心成员

public abstract class EntityBase
{
    // 表名
    public string TableName { get; set; }
    
    // 标识字段(自增字段)
    public string IdentityName { get; set; }
    
    // 主键集合
    public List<string> PrimaryKeys { get; }
    
    // 属性名集合
    public string[] PropertyNames { get; }
    
    // 获取属性值
    protected T getProperty<T>(string propertyName);
    
    // 设置属性值
    protected void setProperty(string propertyName, object value, int length = 0);
    
    // 索引器访问
    public object this[string propertyName] { get; set; }
    
    // 设置外键关系
    protected void SetForeignKey<T>(string foreignKeyName);
    
    // 获取表名
    public string GetTableName();
    
    // 判断属性是否被修改
    public bool PropertyChangedList(string propertyName);
}

2.3.3 实体类定义示例

public class UserEntity : EntityBase
{
    public UserEntity()
    {
        // 设置映射的表名
        TableName = "TbUser";
        
        // 设置自增标识字段
        IdentityName = "ID";
        
        // 设置主键
        PrimaryKeys.Add("ID");
    }
    
    // 自增主键
    public int ID
    {
        get { return getProperty<int>("ID"); }
        set { setProperty("ID", value); }
    }
    
    // 普通字段,指定长度为50
    public string Name
    {
        get { return getProperty<string>("Name"); }
        set { setProperty("Name", value, 50); }
    }
    
    // 可空类型字段
    public DateTime? Birthday
    {
        get { return getProperty<DateTime?>("Birthday"); }
        set { setProperty("Birthday", value); }
    }
}

2.3.4 动态特性的应用

运行时修改表名(分表)

UserEntity user = new UserEntity();
// 根据用户ID进行分表
int tableIndex = userId % 10;
user.TableName = $"TbUser_{tableIndex}";

var result = OQL.From(user).Select().Where(user.ID).END.ToObject();
// 实际查询的是 TbUser_0, TbUser_1 等表

运行时修改主键

UserEntity user = new UserEntity();
user.PrimaryKeys.Clear();
user.PrimaryKeys.Add("LoginName");  // 用登录名作为主键进行删除

user.LoginName = "zhangsan";
EntityQuery<UserEntity>.Instance.Delete(user);
// 生成: DELETE FROM TbUser WHERE LoginName=@LoginName

2.3.5 索引器的妙用

UserEntity user = new UserEntity();

// 使用索引器设置值
user["Name"] = "张三";
user["Status"] = 1;

// 使用索引器获取值
object name = user["Name"];

// 动态排序场景
string sortField = "CreateTime";  // 来自前端参数
var oql = OQL.From(user)
    .Select()
    .OrderBy(user[sortField], "desc")  // 动态排序
    .END;

2.4 OQL:ORM查询语言

2.4.1 OQL的设计理念

OQL(ORM Query Language)是SOD框架独创的ORM查询语言,设计目标是:

  1. 接近SQL语法:让有SQL经验的开发者零学习成本
  2. 类型安全:编译期检查,避免运行时错误
  3. 链式调用:流畅的API设计
  4. 多表支持:支持复杂的关联查询

2.4.2 OQL vs SQL

-- SQL
SELECT ID, Name, Status 
FROM User 
WHERE DeptId = 1 AND Status = 1 
ORDER BY CreateTime DESC
LIMIT 10 OFFSET 0
// OQL
UserEntity user = new UserEntity();
user.DeptId = 1;
user.Status = 1;

var oql = OQL.From(user)
    .Select(user.ID, user.Name, user.Status)
    .Where(user.DeptId, user.Status)
    .OrderBy(order => order.Desc(user.CreateTime))
    .END;
oql.Limit(10, 1);

2.4.3 OQL的语法结构

OQL.From(entity)           // 指定查询的实体对象
   [.InnerJoin/LeftJoin]   // 可选:关联查询
   .Select(...)            // SELECT子句
   .Where(...)             // WHERE子句
   [.GroupBy(...)]         // 可选:分组
   [.Having(...)]          // 可选:分组条件
   .OrderBy(...)           // 排序
   .END                    // 结束构建

// 分页(在END之后调用)
oql.Limit(pageSize, pageIndex);

2.4.4 OQL vs GOQL

GOQL(Generic OQL)是OQL的泛型简化版本,适用于单表查询:

// OQL方式 - 需要先创建实体对象
UserEntity user = new UserEntity();
user.Name = "张三";
var oql = OQL.From(user).Select().Where(user.Name).END;

// GOQL方式 - 无需创建实体对象,使用Lambda表达式
var goql = OQL.FromObject<UserEntity>()
    .Select()
    .Where((cmp, u) => cmp.Property(u.Name) == "张三")
    .END;

// 执行查询
var users = goql.ToList();

2.5 EntityQuery:实体查询执行器

2.5.1 职责与功能

EntityQuery是将OQL翻译为SQL并执行的核心类,主要职责:

  1. 执行OQL查询
  2. 将结果映射到实体对象
  3. 执行实体的增删改操作

2.5.2 核心方法

// 查询单个对象
UserEntity user = EntityQuery<UserEntity>.QueryObject(oql, db);

// 查询对象列表
List<UserEntity> users = EntityQuery<UserEntity>.QueryList(oql, db);

// 查询带子实体的对象列表
List<OrderEntity> orders = EntityQuery<OrderEntity>.QueryListWithChild(oql, db);

// 执行OQL(用于UPDATE/DELETE)
int affected = EntityQuery<UserEntity>.ExecuteOql(oql, db);

// 插入实体
EntityQuery<UserEntity>.Instance.Insert(user, db);

// 更新实体
EntityQuery<UserEntity>.Instance.Update(user, db);

// 删除实体
EntityQuery<UserEntity>.Instance.Delete(user, db);

2.5.3 批量操作

// 批量插入
List<UserEntity> users = new List<UserEntity>() { ... };
foreach(var user in users)
{
    EntityQuery<UserEntity>.Instance.Insert(user, db);
}

// 批量更新(使用OQL)
UserEntity user = new UserEntity();
user.Status = 0;  // 设置要更新的值

var oql = OQL.From(user)
    .Update(user.Status)
    .Where(cmp => cmp.Property(user.DeptId) == 10)
    .END;

int affected = EntityQuery<UserEntity>.ExecuteOql(oql, db);
// 生成: UPDATE TbUser SET Status=0 WHERE DeptId=10

2.6 EntityContainer:数据容器

2.6.1 设计目的

EntityContainer用于处理多表关联查询的结果映射,当查询涉及多个表时,可以将结果映射到不同的类型。

2.6.2 使用场景

// 多表关联查询
OrderEntity order = new OrderEntity();
UserEntity user = new UserEntity();

var oql = OQL.From(order)
    .InnerJoin(user).On(order.UserId, user.ID)
    .Select()
    .Where(cmp => cmp.Property(order.Status) == 1)
    .END;

// 使用EntityContainer映射结果
EntityContainer ec = new EntityContainer(oql, db);

// 映射到匿名类型
var list = ec.MapToList(() => new {
    OrderId = order.ID,
    OrderName = order.Name,
    UserName = user.Name,
    UserPhone = user.Phone
});

// 映射到指定类型
var orderList = ec.MapToList<OrderEntity>();
var userList = ec.MapToList<UserEntity>();

2.6.3 复杂映射示例

// 查询订单及用户信息,进行计算和格式化
var list = ec.MapToList(() => new OrderViewModel {
    OrderId = order.ID,
    OrderNo = order.OrderNo,
    TotalPrice = order.Price.ToString("C"),  // 货币格式
    UserName = user.Name,
    UserAge = DateTime.Now.Year - user.Birthday.Year,  // 计算年龄
    StatusText = order.Status == 1 ? "已完成" : "进行中"
});

2.7 DbContext:数据上下文

2.7.1 Code First支持

DbContext提供Code First开发模式支持,可以根据实体类自动创建数据表:

public class MyDbContext : DbContext
{
    public MyDbContext() : base("local")  // 连接配置名
    {
    }
    
    protected override bool CheckAllTableExists()
    {
        // 检查并创建表
        CheckTableExists<UserEntity>();
        CheckTableExists<OrderEntity>();
        
        // 创建表后初始化(如创建索引)
        InitializeTable<OrderEntity>("CREATE INDEX idx_userId ON {0}(UserId)");
        
        return true;
    }
}

2.7.2 CRUD操作

var context = new MyDbContext();

// 添加
context.Add(user);

// 批量添加
context.AddList(users);

// 更新
context.Update(user);

// 删除
context.Remove(user);

// 事务
bool success = context.Transaction(ctx => {
    ctx.Add(order);
    ctx.AddList(orderItems);
}, out string errorMessage);

2.8 组件协作流程

2.8.1 查询流程

用户代码 → OQL构建器 → OQL对象
              ↓
       EntityQuery.QueryList()
              ↓
       SQL生成(根据AdoHelper类型)
              ↓
       AdoHelper.ExecuteReader()
              ↓
       结果映射(反射或表达式树)
              ↓
       返回实体对象列表

2.8.2 插入流程

用户代码 → 实体对象
              ↓
       EntityQuery.Insert()
              ↓
       生成INSERT SQL(排除未修改字段)
              ↓
       AdoHelper.ExecuteNonQuery()
              ↓
       获取自增ID(如果有)
              ↓
       回填实体对象的标识字段

2.8.3 更新流程

用户代码 → 修改实体属性
              ↓
       EntityQuery.Update()
              ↓
       生成UPDATE SQL(只更新修改过的字段)
              ↓
       AdoHelper.ExecuteNonQuery()
              ↓
       返回受影响行数

2.9 本章小结

本章详细介绍了SOD框架的核心架构和主要组件:

  1. AdoHelper:抽象数据访问层,屏蔽数据库差异
  2. EntityBase:充血实体类基类,支持动态映射和状态追踪
  3. OQL/GOQL:类SQL的ORM查询语言,链式调用
  4. EntityQuery:执行查询和增删改操作
  5. EntityContainer:处理多表查询的结果映射
  6. DbContext:提供Code First和事务支持

理解这些核心组件的设计思想和协作方式,是掌握SOD框架的基础。在后续章节中,我们将深入学习每个组件的具体使用方法。


下一章预告:第三章将介绍如何快速入门SOD框架,包括环境配置、项目搭建和第一个示例程序。