Sod logo

Sod

Community
znlgis
sod

Use when needing a multi-paradigm .NET ORM — EntityBase + EntityQuery CRUD, OQL chain queries with oql.Limit paging, MyBatis-style SQL-MAP XML via SqlMapper, AdoHelper raw SQL, MyDB.GetDBHelperByConnectionName. Also for identity keys not written back after Insert, dirty-field updates, and provider switching across SqlServer/MySql/DaMeng/Kingbase. PDF.NET SOD: ORM + SQL-MAP + OQL.

Overview

Publisherznlgis
Repositoryopengis-skills
Skill namesod
Stars
76
Forks
12
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by znlgis on GitHub. Read the source before you install it.

Installation

Install the Sod AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/znlgis/opengis-skills/tree/main/csharp/sod
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/znlgis/opengis-skills.git /tmp/opengis-skills
mkdir -p .claude/skills
cp -r /tmp/opengis-skills/csharp/sod .claude/skills/sod
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Sod in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Sod on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Sod is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

项目地址: https://github.com/znlgis/SOD(镜像仓库,最后提交 2025-07-05;国内主仓库见 https://gitee.com/znlgis/SOD,截至 2026-10 仍可访问但更新缓慢)

官网: https://www.pwmis.com/sod/

官方文档: http://www.pwmis.com/sod/

NuGet: PDF.NET.SOD

NuGet(.NET 6+): PWMIS.SOD

最新版本: PDF.NET.SOD 7.0.1 / PWMIS.SOD 6.0.3(截至 2026-10,NuGet 实测)

许可证: Apache-2.0

概述

SOD 由 PDF.NET 演化而来,主要特点:

  • 混合 ORM 模式:原生 SQL + ORM + SQL-MAP(XML 配置)+ OQL(对象查询语言)
  • 多数据库:SqlServer / Oracle / MySQL / PostgreSQL / SQLite / Access / 达梦 DM / 人大金仓 / 神舟通用
  • AdoHelper:屏蔽底层 Provider 差异
  • 实体类:EntityBase,支持脏字段跟踪、字段映射、状态机
  • OQL:链式 API 查询、连接、分组、聚合
  • SQL-MAP:XML 写 SQL,Mybatis 风格
  • 读写分离:主从配置
  • 缓存与监控:内置 SQL 性能日志

安装

方式一:dotnet CLI

bash
# .NET 6+ 用 PWMIS.SOD(新版核心库)
dotnet add package PWMIS.SOD

# .NET Framework / netstandard2.0 用 PDF.NET.SOD 系列
dotnet add package PDF.NET.SOD.Core

# 对应数据库 Provider
dotnet add package PDF.NET.SOD.MySQL.Provider
dotnet add package PDF.NET.SOD.PostgreSQL.Provider

方式二:PackageReference

xml
<ItemGroup>
  <PackageReference Include="PWMIS.SOD" Version="6.0.3" />
</ItemGroup>

验证安装

bash
dotnet list package | grep -i sod

两个包的实测结构:PWMIS.SOD 6.0.3 提供 lib/net6.0/PWMIS.SOD.Core.dll;PDF.NET.SOD 7.0.1 只含 PWMIS.SOD.Core.Extensions.dll,完整核心在 PDF.NET.SOD.Core 7.0.1 里。按目标框架选包,不要混装。


核心 API 速查

对象入口说明
数据访问入口MyDB.GetDBHelperByConnectionName(name) / MyDB.GetDBHelperByProviderString(cs, provider)返回 AdoHelper(db,继承自 CommonDB),屏蔽底层 Provider 差异
实体基类EntityBaseTableName / IdentityName / PrimaryKeys;属性用 getProperty<T>() / setProperty()
实体 CRUDnew EntityQuery<T>(db)Insert / Update(仅脏字段)/ Delete / GetList / GetEntity
OQL 链式查询OQL.From(entity).Select(...).Where(...).OrderBy(...).END支持多表连接、分组、聚合;oql.Limit(pageSize, pageIndex) 分页
SQL-MAPnew SqlMapper(db).ExecuteList<T>("Map.Statement", param)XML 写 SQL(MyBatis 风格),SqlMapTool 可生成强类型 DAL
原生 SQLdb.ExecuteDataSet(...) / db.ExecuteNonQuery(...) / db.GetParameter(...)用 AdoHelper 直接执行
事务db.BeginTransaction() → db.Commit() / db.Rollback()均定义在 CommonDB 上,AdoHelper 继承而来;没有 UseTransaction 辅助方法

配置连接字符串(App.config / appsettings)

xml
<connectionStrings>
  <add name="local" providerName="SqlServer"
       connectionString="server=.;database=demo;uid=sa;pwd=..." />
</connectionStrings>

或代码:

csharp
using PWMIS.DataProvider.Data;
var db = MyDB.GetDBHelperByProviderString(
    "server=.;database=demo;uid=sa;pwd=...", "SqlServer");

实体类

csharp
using PWMIS.DataMap.Entity;

[Serializable]
public class User : EntityBase
{
    public User() {
        TableName  = "Users";
        IdentityName = "Id";        // 自增列
        PrimaryKeys.Add("Id");
    }

    public int Id        { get => getProperty<int>("Id");
                           set => setProperty("Id", value); }
    public string Name   { get => getProperty<string>("Name");
                           set => setProperty("Name", value, 50); }
    public DateTime Time { get => getProperty<DateTime>("CreateTime");
                           set => setProperty("CreateTime", value); }
}

可通过 SOD CodeMaker 或 EntityBuilder 自动生成。


CRUD(EntityQuery)

csharp
using PWMIS.DataMap.Entity;

var db = MyDB.GetDBHelperByConnectionName("local");
var q  = new EntityQuery<User>(db);

var u = new User { Name = "Tom", Time = DateTime.Now };
q.Insert(u);                                     // INSERT

u.Name = "Tom2";
q.Update(u);                                     // UPDATE(仅脏字段)

var list = q.GetList(top: 10);                  // SELECT TOP 10
var u1   = q.GetEntity(new User { Id = 1 });    // by PK

q.Delete(u1);                                    // DELETE

OQL(链式查询)

csharp
var u = new User();
var oql = OQL.From(u)
            .Select(u.Id, u.Name)
            .Where(cmp => cmp.Comparer(u.Id, ">", 10) &
                          cmp.Comparer(u.Name, "like", "%T%"))
            .OrderBy(o => o.Asc(u.Id))
            .END;

oql.Limit(20, 1);    // 第 1 页,每页 20 条

var list = EntityQuery<User>.QueryList(oql, db);

聚合:

csharp
var sum = OQL.From(u).Select(u.Id.Sum()).END;
int total = (int)EntityQuery.ExecuteOql(sum, db);

多表连接

csharp
var u = new User();   var o = new Order();
var oql = OQL.From(u)
            .InnerJoin(o).On(u.Id, o.UserId)
            .Select(u.Name, o.Amount)
            .END;

SQL-MAP(XML 模式)

Maps/UserMap.xml:

xml
<sqlMap name="User">
  <statement name="ListByName" desc="按姓名查">
    <![CDATA[
    select * from Users where Name like @Name
    ]]>
  </statement>
</sqlMap>
csharp
var dal = new SqlMapper(db);
var rows = dal.ExecuteList<User>("User.ListByName",
    new { Name = "%Tom%" });

通过 SOD 工具(SqlMapTool)从 XML 自动生成强类型 DAL 类。


AdoHelper(原生 SQL)

csharp
var ds = db.ExecuteDataSet("select * from Users where Id=@Id",
            CommandType.Text, db.GetParameter("@Id", 1));

int rows = db.ExecuteNonQuery("update Users set Name=@N where Id=@Id",
    CommandType.Text,
    db.GetParameter("@N",  "Tom"),
    db.GetParameter("@Id", 1));

事务

csharp
db.BeginTransaction();
try {
    q.Insert(u1);
    q.Insert(u2);
    db.Commit();
} catch {
    db.Rollback();
    throw;
}

批量写入时可用 q.Insert(new List<User> { u1, u2 }) 一次提交;SOD 没有 UseTransaction(() => {...}) 这种委托式包装,事务边界要自己用 BeginTransaction() / Commit() 显式写,CommonDB.OnErrorRollback 只在内部错误处理里生效。


读写分离

通过 MyDB.GetDBHelperByConnectionName(...) 选择不同连接配置;SOD 支持主从切换:

xml
<add name="local-master" providerName="SqlServer" connectionString="..."/>
<add name="local-slave"  providerName="SqlServer" connectionString="..."/>

写走 master,读走 slave;或借助 IReadDb / IWriteDb 接口。


多数据库适配

仅替换 providerName:

数据库providerName
SQL ServerSqlServer
OracleOracle
MySQLMySql
PostgreSQLPostgreSQL
SQLiteSqlite
达梦DaMeng
人大金仓Kingbase
神通OSCAR

性能与监控

  • 启用 MyDB.SQL_LOG_INFO 输出慢 SQL
  • db.CommandTimeOut
  • 连接池大小通过连接字符串
  • OQL 大数据量分页用 Limit(),不要 ToList 全量

典型工作流

工作流一:建实体并完成一次 CRUD

  1. 实体继承 EntityBase,标好 TableName、IdentityName、PrimaryKeys,属性一律用 getProperty<T>() / setProperty() 声明
  2. 新增用 EntityQuery<T> 的 Instance + Insert(),插入后从实体上取回填的自增主键
  3. 改单个字段用 setProperty 后 Update(),只提交变更字段
  4. 删除/按条件批量操作走 OQL,或直接用 AdoHelper 执行原生 SQL

工作流二:复杂查询与分页

  1. 条件复杂时用 OQL 链式 API 拼查询,固定 SQL 场景写 SQL-MAP XML 并用 SqlMapTool 生成强类型 DAL
  2. 分页用 oql.Limit(pageSize, pageIndex),不要 ToList() 后手工分页
  3. 慢查询打开 MyDB.SQL_LOG_INFO 看输出,必要时调 CommandTimeOut

工作流三:换数据库 / 读写分离

  1. 换库只需要改连接字符串的 providerName(SqlServer / MySql / PostgreSQL / DaMeng 等)
  2. 读写分离:分别配主从连接串,写走 master、读走 slave
  3. 事务要在同一个 AdoHelper(CommonDB)实例里 BeginTransaction() → 操作 → Commit()/Rollback()

常见问题

问题解决
字段映射错误使用 MapField(...) 指定列名
自增主键未填回IdentityName 设置正确
中文乱码数据库用 utf8mb4 / NVARCHAR
事务跨连接失败使用同一 AdoHelper 实例(事务挂在 CommonDB 上,换实例即换事务)
找不到 UseTransaction / GetDBHelperByConnectionString6.0/7.0 版没有这两个成员:事务用 BeginTransaction()/Commit()/Rollback(),按连接串取 helper 用 MyDB.GetDBHelperByProviderString(cs, providerName)
OQL 查全表把内存吃满改用 oql.Limit(pageSize, pageIndex) 分页,避免 ToList() 全量取回

AI 使用建议

推荐工作流

  1. 建实体类:继承 EntityBase,设置 TableName、IdentityName、PrimaryKeys,属性用 getProperty<T>() / setProperty()
  2. 选查询方式:简单 CRUD → EntityQuery<T>;复杂条件 → OQL 链式 API;固定 SQL → SQL-MAP XML
  3. 多数据库切换:仅改连接字符串的 providerName(SqlServer / MySql / PostgreSQL / DaMeng 等)
  4. 读写分离:配置主从连接字符串,写走 master,读走 slave
  5. 事务:同一 AdoHelper 实例内 BeginTransaction() → 操作 → Commit() / Rollback()(无 UseTransaction 委托式 API)

关键模式与常见陷阱

  • 实体属性声明:必须用 getProperty<T>(name) / setProperty(name, value, size),不能用自动属性
  • 自增主键回填:IdentityName 必须设置正确,否则 INSERT 后 Id 不更新
  • 脏字段跟踪:Update() 只提交变更字段(调用 setProperty 的字段),性能优于全量更新
  • OQL 分页:用 oql.Limit(pageSize, pageIndex) 分页,不要 ToList 后手动分页
  • SQL-MAP 工具链:用 SOD 的 SqlMapTool 从 XML 生成强类型 DAL,手写 XML 容易拼错

如何选择正确方案

场景推荐方案
政企项目(达梦/金仓/神通)SOD(多数据库支持最全)
追求开发效率SqlSugar(链式查询更现代)
MyBatis 用户迁移SOD SQL-MAP 模式
新项目评估 SqlSugar vs SOD 的数据库支持列表

相关技能

  • sqlsugar — 同为 .NET ORM,链式查询更现代化,生态更活跃:../sqlsugar/SKILL.md
  • furion — .NET Web 框架,Furion 内置 SqlSugar 集成,SOD 亦可配合使用:../furion/SKILL.md
  • npoi — 查询结果导出 Excel 时与 SOD 组合使用:../npoi/SKILL.md
  • admin-net-backend — 基于 Furion + SqlSugar 的后台框架,可对照其分层与 DAL 组织方式:../admin-net-backend/SKILL.md

参考资源

Frequently asked questions

What does the Sod AI skill do?

Use when needing a multi-paradigm .NET ORM — EntityBase + EntityQuery CRUD, OQL chain queries with oql.Limit paging, MyBatis-style SQL-MAP XML via SqlMapper, AdoHelper raw SQL, MyDB.GetDBHelperByConnectionName. Also for identity keys not written back after Insert, dirty-field updates, and provider switching across SqlServer/MySql/DaMeng/Kingbase. PDF.NET SOD: ORM + SQL-MAP + OQL.

Why use Sod on TypingMind?

Because you install it once and use it with any model. Sod is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Sod in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/znlgis/opengis-skills/tree/main/csharp/sod. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Sod?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Sod?

As many as you like. As long as a model supports skills, you can use Sod with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Sod AI skill free?

Yes. It is published on GitHub by znlgis under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇