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

推荐订阅源

T
Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
T
The Blog of Author Tim Ferriss
Recent Announcements
Recent Announcements
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
MongoDB | Blog
MongoDB | Blog
U
Unit 42
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
P
Privacy International News Feed
L
LINUX DO - 最新话题
博客园_首页
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
K
Kaspersky official blog
C
Cisco Blogs
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
罗磊的独立博客
MyScale Blog
MyScale Blog
Last Week in AI
Last Week in AI
A
About on SuperTechFans
G
GRAHAM CLULEY
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
GbyAI
GbyAI
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
D
DataBreaches.Net
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
I
InfoQ
T
The Exploit Database - CXSecurity.com
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - 叶小钗
Project Zero
Project Zero

博客园 - 我才是银古

第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 博客园 - 我才是银古

第三章:快速入门与环境配置

3.1 开发环境准备

3.1.1 必要的开发工具

工具 要求 说明
Visual Studio 2019/2022 推荐使用最新版本
.NET SDK 2.0 - 8.0 根据项目目标框架选择
NuGet 内置 包管理工具
SQL Server / MySQL / 其他 任意版本 开发用数据库

3.1.2 .NET版本与NuGet包对应关系

目标框架 NuGet包名 版本
.NET 6.0+ PWMIS.SOD 6.0+
.NET 5/.NET Core/.NET 4.x PDF.NET.SOD 7.0
.NET 2.0 - 4.x PDF.NET.SOD 6.x及以下

3.1.3 数据库支持

SOD框架内置支持以下数据库:

数据库 内置/扩展 providerName
SQL Server 内置 SqlServer
Access 内置 Access
Oracle 内置 Oracle
SQL CE 内置 SqlCe
OleDb 内置 OleDb
ODBC 内置 Odbc

扩展支持的数据库:

数据库 NuGet包 providerName
MySQL PDF.NET.SOD.MySQL.Provider PWMIS.DataProvider.Data.MySQL,PWMIS.MySqlClient
PostgreSQL PDF.NET.SOD.PostgreSQL.Provider PWMIS.DataProvider.Data.PostgreSQL,PWMIS.PostgreSQLClient
SQLite PDF.NET.SOD.SQLite.Provider PWMIS.DataProvider.Data.SQLite,PWMIS.SQLiteClient
达梦 PWMIS.SOD.DaMeng.Provider PWMIS.DataProvider.Data.Dameng,PWMIS.DamengClient
人大金仓 PWMIS.SOD.Kingbase.Provider PWMIS.DataProvider.Data.Kingbase,PWMIS.KingbaseClient

3.2 创建第一个SOD项目

3.2.1 创建控制台项目

使用Visual Studio:

  1. 打开Visual Studio
  2. 选择"创建新项目"
  3. 选择"控制台应用"模板
  4. 设置项目名称,如:SODDemo
  5. 选择目标框架(推荐.NET 6.0或更高版本)

使用命令行:

# 创建.NET 6.0控制台项目
dotnet new console -n SODDemo -f net6.0

# 进入项目目录
cd SODDemo

3.2.2 安装NuGet包

使用包管理器控制台:

# .NET 6.0及以上版本
Install-Package PWMIS.SOD

# .NET 5及以下版本
Install-Package PDF.NET.SOD

使用命令行:

# .NET 6.0及以上版本
dotnet add package PWMIS.SOD

# .NET 5及以下版本
dotnet add package PDF.NET.SOD

使用NuGet包管理器界面:

  1. 右键项目 → "管理NuGet程序包"
  2. 搜索"PWMIS.SOD"或"PDF.NET.SOD"
  3. 安装最新版本

3.2.3 配置数据库连接

在项目中创建或编辑appsettings.json(.NET Core/5+)或app.config(.NET Framework):

.NET Core/5+项目(appsettings.json):

{
  "ConnectionStrings": {
    "Default": "Server=.;Database=SODDemo;Trusted_Connection=True;TrustServerCertificate=True"
  }
}

然后在代码中配置:

// 设置连接字符串
MyDB.Instance.ConnectionString = "Server=.;Database=SODDemo;...";
MyDB.Instance.DataProvider = new SqlServer();

.NET Framework项目(app.config):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="local" 
         connectionString="Data Source=.;Initial Catalog=SODDemo;Integrated Security=True" 
         providerName="SqlServer"/>
  </connectionStrings>
</configuration>

3.2.4 定义第一个实体类

创建User.cs文件:

using PWMIS.DataMap.Entity;

namespace SODDemo
{
    // 方式1:定义接口类型(用于动态创建实体类)
    public interface IUser
    {
        int ID { get; set; }
        string Name { get; set; }
        string Email { get; set; }
        DateTime CreateTime { get; set; }
    }

    // 方式2:定义完整的实体类
    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); }
        }

        public string Name
        {
            get { return getProperty<string>("Name"); }
            set { setProperty("Name", value, 50); }  // 字段长度50
        }

        public string Email
        {
            get { return getProperty<string>("Email"); }
            set { setProperty("Email", value, 100); }
        }

        public DateTime CreateTime
        {
            get { return getProperty<DateTime>("CreateTime"); }
            set { setProperty("CreateTime", value); }
        }
    }
}

3.2.5 创建数据上下文(可选)

如果需要使用Code First自动创建表:

using PWMIS.DataMap.Entity;

namespace SODDemo
{
    public class DemoDbContext : DbContext
    {
        public DemoDbContext() : base("local")  // 使用配置名"local"
        {
        }

        protected override bool CheckAllTableExists()
        {
            // 检查并创建用户表
            CheckTableExists<UserEntity>();
            return true;
        }
    }
}

3.2.6 编写第一个程序

using System;
using PWMIS.DataProvider.Data;
using PWMIS.DataMap.Entity;
using PWMIS.Core;

namespace SODDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=== SOD框架快速入门示例 ===\n");

            // 1. 初始化数据上下文(自动创建表)
            var context = new DemoDbContext();
            Console.WriteLine("数据库初始化完成!\n");

            // 2. 创建用户数据
            var user = new UserEntity
            {
                Name = "张三",
                Email = "zhangsan@example.com",
                CreateTime = DateTime.Now
            };

            // 3. 插入数据
            int insertResult = context.Add(user);
            if (insertResult > 0)
            {
                Console.WriteLine($"插入成功!用户ID: {user.ID}");
            }

            // 4. 查询数据(使用OQL)
            var queryUser = new UserEntity();
            queryUser.Name = "张三";
            
            var oql = OQL.From(queryUser)
                .Select()
                .Where(queryUser.Name)
                .END;
            
            var users = EntityQuery<UserEntity>.QueryList(oql);
            Console.WriteLine($"\n查询到 {users.Count} 条记录:");
            foreach (var u in users)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}, Email={u.Email}");
            }

            // 5. 更新数据
            user.Email = "zhangsan_new@example.com";
            int updateResult = context.Update(user);
            Console.WriteLine($"\n更新结果:{updateResult} 行受影响");

            // 6. 删除数据
            int deleteResult = context.Remove(user);
            Console.WriteLine($"删除结果:{deleteResult} 行受影响");

            Console.WriteLine("\n=== 示例运行完成 ===");
            Console.ReadKey();
        }
    }
}

3.3 使用AdoHelper直接操作数据库

3.3.1 创建AdoHelper实例

using PWMIS.DataProvider.Data;

// 方式1:从配置文件读取
AdoHelper db = MyDB.GetDBHelperByConnectionName("local");

// 方式2:读取最后一个配置
AdoHelper db = MyDB.GetDBHelper();

// 方式3:直接创建
AdoHelper db = new SqlServer();
db.ConnectionString = "Data Source=.;Initial Catalog=SODDemo;Integrated Security=True";

3.3.2 执行SQL语句

AdoHelper db = MyDB.GetDBHelper();

// 创建表
string createTableSql = @"
CREATE TABLE TbUser (
    ID INT IDENTITY(1,1) PRIMARY KEY,
    Name NVARCHAR(50),
    Email NVARCHAR(100),
    CreateTime DATETIME
)";

try
{
    db.ExecuteNonQuery(createTableSql);
    Console.WriteLine("表创建成功!");
}
catch (Exception ex)
{
    Console.WriteLine($"表已存在或创建失败:{ex.Message}");
}

// 插入数据(参数化查询)
string insertSql = "INSERT INTO TbUser (Name, Email, CreateTime) VALUES (@Name, @Email, @CreateTime)";
var parameters = new IDataParameter[]
{
    db.GetParameter("@Name", "张三"),
    db.GetParameter("@Email", "zhangsan@example.com"),
    db.GetParameter("@CreateTime", DateTime.Now)
};

int rows = db.ExecuteNonQuery(insertSql, CommandType.Text, parameters);
Console.WriteLine($"插入 {rows} 行");

// 查询数据
string selectSql = "SELECT * FROM TbUser WHERE Name = @Name";
var queryParams = new IDataParameter[]
{
    db.GetParameter("@Name", "张三")
};

DataSet ds = db.ExecuteDataSet(selectSql, CommandType.Text, queryParams);
DataTable dt = ds.Tables[0];

foreach (DataRow row in dt.Rows)
{
    Console.WriteLine($"ID={row["ID"]}, Name={row["Name"]}");
}

3.3.3 微型ORM查询

// 使用占位符参数的简化查询
string sql = "SELECT ID, Name, Email FROM TbUser WHERE Name = {0}";

// 方式1:映射到匿名类型
var users = db.ExecuteMapper(sql, "张三")
    .MapToList(reader => new
    {
        ID = reader.GetInt32(0),
        Name = reader.GetString(1),
        Email = reader.GetString(2)
    });

// 方式2:映射到POCO类
var userList = db.QueryList<UserInfo>(sql, "张三");

// UserInfo是一个简单的POCO类
public class UserInfo
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

3.4 使用ORM进行CRUD操作

3.4.1 创建实体类对象

// 方式1:直接创建实体类实例
UserEntity user = new UserEntity();
user.Name = "张三";
user.Email = "zhangsan@example.com";
user.CreateTime = DateTime.Now;

// 方式2:使用接口动态创建
IUser iUser = EntityBuilder.CreateEntity<IUser>();
iUser.Name = "李四";
iUser.Email = "lisi@example.com";

3.4.2 插入数据

AdoHelper db = MyDB.GetDBHelper();
UserEntity user = new UserEntity
{
    Name = "张三",
    Email = "zhangsan@example.com",
    CreateTime = DateTime.Now
};

// 方式1:使用EntityQuery
int result = EntityQuery<UserEntity>.Instance.Insert(user, db);
Console.WriteLine($"插入成功,自增ID: {user.ID}");

// 方式2:使用DbContext
var context = new DemoDbContext();
context.Add(user);

3.4.3 查询数据

// 查询单个对象
UserEntity queryUser = new UserEntity();
queryUser.ID = 1;

var oql = OQL.From(queryUser)
    .Select()
    .Where(queryUser.ID)
    .END;

UserEntity result = EntityQuery<UserEntity>.QueryObject(oql);

// 查询列表
UserEntity listQuery = new UserEntity();
listQuery.Name = "张";  // 模糊匹配

var listOql = OQL.From(listQuery)
    .Select()
    .Where(cmp => cmp.Comparer(listQuery.Name, "like", "张%"))
    .OrderBy(order => order.Desc(listQuery.ID))
    .END;

List<UserEntity> users = EntityQuery<UserEntity>.QueryList(listOql);

3.4.4 更新数据

UserEntity user = new UserEntity();
user.ID = 1;  // 主键

// 先查询
var oql = OQL.From(user).Select().Where(user.ID).END;
UserEntity existUser = EntityQuery<UserEntity>.QueryObject(oql);

// 修改属性
existUser.Email = "new_email@example.com";

// 更新(只更新修改过的字段)
int result = EntityQuery<UserEntity>.Instance.Update(existUser, db);

// 批量更新
UserEntity updateUser = new UserEntity();
updateUser.Email = "batch@example.com";  // 要更新的值

var batchOql = OQL.From(updateUser)
    .Update(updateUser.Email)
    .Where(cmp => cmp.Comparer(updateUser.Name, "like", "张%"))
    .END;

int affected = EntityQuery<UserEntity>.ExecuteOql(batchOql, db);

3.4.5 删除数据

UserEntity user = new UserEntity();
user.ID = 1;

// 方式1:根据主键删除
int result = EntityQuery<UserEntity>.Instance.Delete(user, db);

// 方式2:使用OQL条件删除
var deleteOql = OQL.From(user)
    .Delete()
    .Where(cmp => cmp.Property(user.Name) == "张三")
    .END;

int affected = EntityQuery<UserEntity>.ExecuteOql(deleteOql, db);

// 方式3:使用DbContext
var context = new DemoDbContext();
context.Remove(user);

3.5 使用GOQL简化查询

GOQL(Generic OQL)是OQL的泛型版本,更加简洁:

using PWMIS.Core.Extensions;

// 简单查询
var users = OQL.FromObject<UserEntity>()
    .Select()
    .Where((cmp, u) => cmp.Property(u.Name) == "张三")
    .END
    .ToList();

// 带条件和排序的查询
var pageUsers = OQL.FromObject<UserEntity>()
    .Select(s => new object[] { s.ID, s.Name, s.Email })
    .Where((cmp, u) => cmp.Property(u.CreateTime) >= DateTime.Today)
    .OrderBy((order, u) => order.Desc(u.ID))
    .Limit(10, 1)  // 分页
    .ToList();

// 使用接口类型查询
var iUsers = OQL.FromObject<IUser>()
    .Select()
    .Where((cmp, u) => cmp.Comparer(u.Name, "like", "张%"))
    .ToList();

3.6 完整示例项目

3.6.1 项目结构

SODDemo/
├── Program.cs                 # 主程序
├── Entities/
│   ├── UserEntity.cs         # 用户实体
│   └── OrderEntity.cs        # 订单实体
├── DataAccess/
│   └── DemoDbContext.cs      # 数据上下文
├── Services/
│   └── UserService.cs        # 业务逻辑层
├── app.config                # 配置文件
└── SODDemo.csproj            # 项目文件

3.6.2 完整代码示例

UserEntity.cs:

using PWMIS.DataMap.Entity;
using System;

namespace SODDemo.Entities
{
    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); }
        }

        public string Name
        {
            get { return getProperty<string>("Name"); }
            set { setProperty("Name", value, 50); }
        }

        public string Email
        {
            get { return getProperty<string>("Email"); }
            set { setProperty("Email", value, 100); }
        }

        public int Status
        {
            get { return getProperty<int>("Status"); }
            set { setProperty("Status", value); }
        }

        public DateTime CreateTime
        {
            get { return getProperty<DateTime>("CreateTime"); }
            set { setProperty("CreateTime", value); }
        }
    }
}

DemoDbContext.cs:

using PWMIS.DataMap.Entity;
using SODDemo.Entities;

namespace SODDemo.DataAccess
{
    public class DemoDbContext : DbContext
    {
        public DemoDbContext() : base("local")
        {
        }

        protected override bool CheckAllTableExists()
        {
            CheckTableExists<UserEntity>();
            return true;
        }
    }
}

UserService.cs:

using System;
using System.Collections.Generic;
using PWMIS.DataProvider.Data;
using PWMIS.DataMap.Entity;
using SODDemo.Entities;

namespace SODDemo.Services
{
    public class UserService
    {
        private readonly AdoHelper _db;

        public UserService()
        {
            _db = MyDB.GetDBHelper();
        }

        // 添加用户
        public int AddUser(string name, string email)
        {
            var user = new UserEntity
            {
                Name = name,
                Email = email,
                Status = 1,
                CreateTime = DateTime.Now
            };

            EntityQuery<UserEntity>.Instance.Insert(user, _db);
            return user.ID;
        }

        // 根据ID获取用户
        public UserEntity GetUser(int id)
        {
            var user = new UserEntity { ID = id };
            var oql = OQL.From(user).Select().Where(user.ID).END;
            return EntityQuery<UserEntity>.QueryObject(oql, _db);
        }

        // 获取所有用户
        public List<UserEntity> GetAllUsers()
        {
            var user = new UserEntity();
            var oql = OQL.From(user)
                .Select()
                .Where(cmp => cmp.Property(user.Status) == 1)
                .OrderBy(order => order.Desc(user.ID))
                .END;
            return EntityQuery<UserEntity>.QueryList(oql, _db);
        }

        // 更新用户邮箱
        public bool UpdateEmail(int id, string newEmail)
        {
            var user = GetUser(id);
            if (user == null) return false;

            user.Email = newEmail;
            return EntityQuery<UserEntity>.Instance.Update(user, _db) > 0;
        }

        // 删除用户
        public bool DeleteUser(int id)
        {
            var user = new UserEntity { ID = id };
            return EntityQuery<UserEntity>.Instance.Delete(user, _db) > 0;
        }

        // 分页查询
        public List<UserEntity> GetUsersByPage(int pageIndex, int pageSize, out int totalCount)
        {
            var user = new UserEntity();
            var oql = OQL.From(user)
                .Select()
                .Where(cmp => cmp.Property(user.Status) == 1)
                .OrderBy(order => order.Desc(user.ID))
                .END;

            oql.Limit(pageSize, pageIndex, true);  // true表示同时计算总数
            
            var list = EntityQuery<UserEntity>.QueryList(oql, _db);
            totalCount = oql.PageWithAllRecordCount;
            
            return list;
        }
    }
}

Program.cs:

using System;
using SODDemo.DataAccess;
using SODDemo.Services;

namespace SODDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=== SOD框架完整示例 ===\n");

            // 初始化数据库
            var context = new DemoDbContext();
            Console.WriteLine("数据库初始化完成!\n");

            // 创建服务
            var userService = new UserService();

            // 1. 添加用户
            Console.WriteLine("--- 添加用户 ---");
            int id1 = userService.AddUser("张三", "zhangsan@example.com");
            int id2 = userService.AddUser("李四", "lisi@example.com");
            int id3 = userService.AddUser("王五", "wangwu@example.com");
            Console.WriteLine($"添加了3个用户,ID分别为: {id1}, {id2}, {id3}\n");

            // 2. 查询单个用户
            Console.WriteLine("--- 查询用户 ---");
            var user = userService.GetUser(id1);
            Console.WriteLine($"查询到用户: ID={user.ID}, Name={user.Name}, Email={user.Email}\n");

            // 3. 查询所有用户
            Console.WriteLine("--- 所有用户列表 ---");
            var allUsers = userService.GetAllUsers();
            foreach (var u in allUsers)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}, Email={u.Email}");
            }
            Console.WriteLine();

            // 4. 更新用户
            Console.WriteLine("--- 更新用户邮箱 ---");
            bool updated = userService.UpdateEmail(id1, "zhangsan_new@example.com");
            Console.WriteLine($"更新结果: {(updated ? "成功" : "失败")}\n");

            // 5. 分页查询
            Console.WriteLine("--- 分页查询 ---");
            var pageUsers = userService.GetUsersByPage(1, 2, out int totalCount);
            Console.WriteLine($"总记录数: {totalCount}, 当前页记录数: {pageUsers.Count}");
            foreach (var u in pageUsers)
            {
                Console.WriteLine($"  ID={u.ID}, Name={u.Name}");
            }
            Console.WriteLine();

            // 6. 删除用户
            Console.WriteLine("--- 删除用户 ---");
            bool deleted = userService.DeleteUser(id3);
            Console.WriteLine($"删除用户 {id3} 结果: {(deleted ? "成功" : "失败")}\n");

            Console.WriteLine("=== 示例运行完成 ===");
            Console.ReadKey();
        }
    }
}

3.7 常见问题与解决方案

3.7.1 连接字符串配置问题

问题:找不到连接配置

解决:确保app.config或appsettings.json配置正确,并且配置文件已复制到输出目录。

<!-- app.config 需要在配置正确的节点下 -->
<configuration>
  <connectionStrings>
    <add name="local" connectionString="..." providerName="SqlServer"/>
  </connectionStrings>
</configuration>

3.7.2 数据库提供程序问题

问题:无法加载数据库提供程序

解决

  1. 安装对应的NuGet包
  2. 确保providerName格式正确
<!-- 扩展提供程序的格式 -->
<add name="mysql" 
     connectionString="Server=localhost;Database=test;Uid=root;Pwd=123456;" 
     providerName="PWMIS.DataProvider.Data.MySQL,PWMIS.MySqlClient"/>

3.7.3 实体类映射问题

问题:查询结果为空或字段值为null

解决

  1. 检查TableName是否正确
  2. 检查属性名与字段名是否匹配
  3. 确认getProperty/setProperty中的字段名
// 检查映射配置
public class UserEntity : EntityBase
{
    public UserEntity()
    {
        TableName = "TbUser";  // 确保表名正确
    }
    
    public string Name
    {
        get { return getProperty<string>("Name"); }  // 确保字段名正确
        set { setProperty("Name", value, 50); }
    }
}

3.7.4 自增ID未回填

问题:插入后实体类的ID属性为0

解决:确保设置了IdentityName

public UserEntity()
{
    TableName = "TbUser";
    IdentityName = "ID";      // 必须设置自增字段名
    PrimaryKeys.Add("ID");    // 添加主键
}

3.8 本章小结

本章介绍了SOD框架的快速入门内容:

  1. 开发环境准备:安装必要的工具和NuGet包
  2. 创建项目:使用VS或命令行创建项目
  3. 配置连接:配置数据库连接字符串
  4. 定义实体类:创建继承EntityBase的实体类
  5. CRUD操作:使用EntityQuery和OQL进行数据操作
  6. GOQL简化:使用泛型OQL简化代码

通过本章的学习,你应该能够使用SOD框架完成基本的数据库操作。在接下来的章节中,我们将深入学习实体类映射、OQL查询语言等高级特性。


下一章预告:第四章将深入讲解SOD实体类的定义、元数据映射机制以及高级映射技巧。