C#连接Oracle最佳实践:Oracle.ManagedDataAccess实战指南
简介本资源是一份面向C#开发者、特别是.NET平台数据库应用工程师的Oracle数据库接入实战教程聚焦于轻量、免客户端安装的Oracle.ManagedDataAccess驱动集成方案解决传统ODP.NET依赖本地Oracle客户端的部署痛点。压缩包共297个文件含85个核心dll含Oracle.ManagedDataAccess及配套依赖、50个xml配置与文档说明、36个txt使用指南与连接参数示例、8个cs源码文件含已封装好的OracleHelper操作类以及sln工程文件和csproj项目配置整体11.2MB结构完整、开箱即用。已有782人学习下载资源提供全开源可运行代码支持IP/用户名/密码直连封装了增删改查、事务处理、DataSet填充等常用功能已在多个实际项目中验证稳定代码注释清晰、逻辑分层明确适合初学者快速上手也便于中高级开发者二次扩展与集成。1. C# 连接 Oracle 的快速方法为什么不用 ODP.NET Core 而选 Oracle.ManagedDataAccess你写完一个 WinForms 上位机准备连 Oracle 19c 生产库——结果卡在连接字符串上两小时ORA-12154: TNS:could not resolve the connect identifier换用System.Data.OracleClient编译直接报错“已弃用且不支持 .NET Core/.NET 5”查 GitHub 开源项目发现 90% 的 C# 工业软件、ERP 集成工具、MES 数据采集模块都在用Oracle.ManagedDataAccess简称 ODP.NET Managed Driver而不是老式Unmanaged版本。它不依赖本地 Oracle Client 安装、纯托管、NuGet 一键集成、支持 .NET 6/7/8、能跑在 Linux Docker 容器里——这才是真正“开箱即用”的 C# 连 Oracle 快速路径。本文不是泛泛讲“怎么连”而是按一线工程师真实交付节奏从零开始建控制台项目 → 用最小依赖连通测试库 → 处理中文乱码、日期精度、LOB 大字段 → 压测连接池泄漏 → 最后落地到一个可嵌入 WinForms 的稳定数据访问层。所有代码基于 .NET 8全部开源无商业组件、无隐藏 DLL每一步命令、配置、参数都经生产环境验证。适合正在做设备数据采集、ERP 接口开发、或需要对接 Oracle EBS/WIP 表结构的 C# 开发者。2. 从零初始化创建项目、安装驱动、写第一个成功连接2.1 创建 .NET 8 控制台项目并引用 Oracle.ManagedDataAccess不要用 Visual Studio 图形界面点点点——命令行才是可控起点。打开终端PowerShell 或 CMD执行dotnet new console -n OracleQuickStart -f net8.0 cd OracleQuickStart dotnet add package Oracle.ManagedDataAccess --version 23.6.0提示版本号必须显式指定。截至 2024 年中23.6.0是 Oracle 官方最新稳定版对应 Oracle Database 23c/19c/12c 兼容性最佳避免用--prerelease或默认最新版——曾有团队因自动升级到23.7.0-beta导致OracleCommand.BindByName true行为变更引发批量更新字段错位。项目生成后OracleQuickStart.csproj中应含以下PackageReferencePackageReference IncludeOracle.ManagedDataAccess Version23.6.0 /2.2 构造最小可行连接字符串适配 Oracle 12c/19c/23cOracle 连接字符串是玄学重灾区。别抄网上“Data Source...”模糊写法——必须分清三种模式模式适用场景示例连接字符串关键特征Easy Connect开发/测试库无tnsnames.oraUser Idscott;Passwordtiger;Data Sourcelocalhost:1521/XE端口SID/ServiceName 直连无需本地配置TNS Alias生产环境已有tnsnames.oraUser Idscott;Passwordtiger;Data SourceORCLPRODData Source后填别名驱动自动读取%ORACLE_HOME%\network\admin\tnsnames.oraConnect Descriptor跨网段/高可用RAC、需显式指定协议User Idscott;Passwordtiger;Data Source(DESCRIPTION(ADDRESS(PROTOCOLTCP)(HOST10.20.30.40)(PORT1521))(CONNECT_DATA(SERVICE_NAMEorclpdb1)))完整描述绕过 tnsnames 文件最可控✅推荐新手起步用 Easy Connectstring connectionString User Idscott;Passwordtiger;Data Sourcelocalhost:1521/XE; // 注意XE 是 Oracle Express Edition 默认 ServiceName19c/23c 通常用 orclpdb1CDB 中的 PDB 名参数说明User Id/Password明文账号密码生产环境必须加密见第 5 章Data Source格式为host:port/SERVICE_NAME非 SID12c 默认启 PDB用 SERVICE_NAMEPoolingtrue默认开启连接池启用勿手动设false否则性能断崖下跌2.3 写第一段可运行的连接验证代码新建Program.cs替换为以下内容无异常捕获的极简版只为验证通路using Oracle.ManagedDataAccess.Client; string connStr User Idscott;Passwordtiger;Data Sourcelocalhost:1521/XE; using (var conn new OracleConnection(connStr)) { conn.Open(); Console.WriteLine($✅ 连接成功服务器版本{conn.ServerVersion}); Console.WriteLine($✅ 当前数据库{conn.DatabaseName}); }运行dotnet run输出类似✅ 连接成功服务器版本19.0.0.0.0 ✅ 当前数据库XE逻辑说明using确保Dispose()被调用归还连接到池不是关闭物理连接conn.ServerVersion返回 Oracle 实际版本号比查v$version更快若报ORA-12541: No listener检查 Oracle 监听服务是否启动lsnrctl status若报ORA-12154确认XE是 ServiceName非 SID或改用 Connect Descriptor 模式3. 生产级数据操作查询、参数化、事务与大字段处理3.1 安全查询永远不用字符串拼接用 OracleParameter 绑定这是血泪经验——某 MES 项目因拼接WHERE emp_name name 被注入; DROP TABLE emp; --直接删库。正确写法string sql SELECT empno, ename, hiredate FROM emp WHERE deptno :deptId AND hiredate :startDate; using (var conn new OracleConnection(connStr)) { conn.Open(); using (var cmd new OracleCommand(sql, conn)) { // 绑定参数名称必须与 SQL 中 :xxx 一致注意冒号 cmd.Parameters.Add(new OracleParameter(deptId, 10)); cmd.Parameters.Add(new OracleParameter(startDate, new DateTime(1981, 1, 1))); using (var reader cmd.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(${reader.GetInt32(0)} | {reader.GetString(1)} | {reader.GetDateTime(2):yyyy-MM-dd}); } } } }关键细节参数名deptId前不加冒号OracleParameter构造函数自动处理OracleParameter类型推断传int→OracleDbType.Int32传DateTime→OracleDbType.Date若需显式指定类型如防止NUMBER(10,2)被误读为decimalcmd.Parameters.Add(new OracleParameter(salary, OracleDbType.Decimal) { Value 5000.5m });3.2 批量插入用 OracleBulkCopy 替代 1000 条 ExecuteNonQuery对万级数据导入ExecuteNonQuery循环是性能黑洞。OracleBulkCopy是 Oracle 官方提供的高速通道类似 SQL Server 的SqlBulkCopy// 准备 DataTable列名必须与目标表完全一致 var dt new DataTable(); dt.Columns.Add(EMPNO, typeof(int)); dt.Columns.Add(ENAME, typeof(string)); dt.Columns.Add(HIREDATE, typeof(DateTime)); // ... 添加 1000 行数据 using (var conn new OracleConnection(connStr)) { conn.Open(); using (var bulkCopy new OracleBulkCopy(conn)) { bulkCopy.DestinationTableName emp; // 目标表名 bulkCopy.BatchSize 1000; // 每批提交行数 bulkCopy.BulkCopyTimeout 300; // 超时秒数 bulkCopy.WriteToServer(dt); // 一次性写入 } }避坑前提目标表必须有主键或唯一约束否则可能重复插入DataTable列顺序不必与表一致但列名必须精确匹配大小写敏感不支持INSERT ... SELECT类复杂逻辑仅纯数据灌入3.3 处理 CLOB/BLOB读写超长文本与二进制文件Oracle 中CLOB文本和BLOB二进制不能用GetString()/GetBytes()直接读——会触发ORA-01405: fetched column value is NULL或内存溢出。正确姿势// 插入 CLOB例如日志文本 4000 字符 string longLog new string(X, 10000); using (var conn new OracleConnection(connStr)) { conn.Open(); using (var cmd new OracleCommand(INSERT INTO logs(id, content) VALUES (:id, :content), conn)) { cmd.Parameters.Add(new OracleParameter(id, 1001)); // 关键用 OracleClob 分块写入 var clobParam new OracleParameter(content, OracleDbType.Clob) { Value longLog }; cmd.Parameters.Add(clobParam); cmd.ExecuteNonQuery(); } } // 查询 CLOB流式读取避免内存爆炸 using (var conn new OracleConnection(connStr)) { conn.Open(); using (var cmd new OracleCommand(SELECT content FROM logs WHERE id :id, conn)) { cmd.Parameters.Add(new OracleParameter(id, 1001)); using (var reader cmd.ExecuteReader()) { if (reader.Read()) { OracleClob clob reader.GetOracleClob(0); // 流式读取每次 8192 字节 var buffer new char[8192]; int charsRead; while ((charsRead clob.Read(buffer, 0, buffer.Length)) 0) { Console.Write(new string(buffer, 0, charsRead)); } } } } }参数说明OracleClob/OracleBlob是 Oracle 驱动特有类型GetOracleClob()比GetFieldValueOracleClob()更安全写入时Value string自动转 CLOB读取时务必用Read()分块而非Value.ToString()会加载全量到内存4. 连接池与资源泄漏为什么你的程序跑一天就卡死4.1 理解 Oracle.ManagedDataAccess 连接池机制这不是黑匣子——ODP.NET Managed Driver 的连接池是进程级静态对象由OracleConnection构造函数隐式管理。关键事实每个唯一连接字符串对应一个独立连接池区分大小写、空格、顺序池大小默认Min Pool Size1; Max Pool Size100; Incr Pool Size5物理连接在Close()后不销毁而是归还池中复用Dispose()效果等同Close()连接泄漏 未调用 Close()/Dispose() → 连接永远占用池槽位 → 达到 Max Pool Size 后新请求阻塞4.2 用 PerfView 或 dotnet-counters 定位泄漏在项目根目录执行# 安装诊断工具 dotnet tool install -g dotnet-counters # 启动应用并监控 dotnet-counters monitor -p pid --counters Oracle.ManagedDataAccess关注指标Active Connections当前已打开未关闭的连接数Pooled Connections池中空闲连接数Total Connections Opened进程启动后总打开次数若Active Connections持续上涨不回落 → 100% 存在泄漏。4.3 三类高频泄漏场景与修复代码场景 1Reader 未关闭导致连接无法归还池❌ 错误写法reader未Disposevar cmd new OracleCommand(SELECT * FROM emp, conn); var reader cmd.ExecuteReader(); // reader 占用连接 while (reader.Read()) { ... } // reader.Close() 缺失连接被锁死✅ 正确写法嵌套usingusing (var cmd new OracleCommand(SELECT * FROM emp, conn)) using (var reader cmd.ExecuteReader()) // reader.Dispose() 自动调用 conn.Close() { while (reader.Read()) { ... } } // reader 和 cmd 同时释放场景 2异步方法中忘记 await导致上下文丢失❌ 错误写法await缺失async方法未等待public async Taskstring GetEmpName(int empNo) { using (var conn new OracleConnection(connStr)) { await conn.OpenAsync(); var cmd new OracleCommand(SELECT ename FROM emp WHERE empno :id, conn); cmd.Parameters.Add(new OracleParameter(id, empNo)); return cmd.ExecuteScalar()?.ToString(); // ⚠️ 这里没 await } } // 调用方var name GetEmpName(7369); // 同步调用async 方法被丢弃✅ 正确写法全程 awaitpublic async Taskstring GetEmpName(int empNo) { using (var conn new OracleConnection(connStr)) { await conn.OpenAsync(); // ✅ await using (var cmd new OracleCommand(SELECT ename FROM emp WHERE empno :id, conn)) { cmd.Parameters.Add(new OracleParameter(id, empNo)); var result await cmd.ExecuteScalarAsync(); // ✅ await return result?.ToString(); } } } // 调用方var name await GetEmpName(7369);场景 3全局单例 Connection 复用反模式❌ 错误写法一个连接被多线程并发使用public static class DbHelper { private static readonly OracleConnection _sharedConn new OracleConnection(connStr); public static OracleConnection GetConnection() _sharedConn; // ❌ 危险 }✅ 正确写法每次 New Connection靠池复用public static class DbHelper { public static OracleConnection GetConnection() new OracleConnection(connStr); // ✅ 每次新实例池自动管理 }为什么单例连接错OracleConnection不是线程安全的。多线程同时调用ExecuteReader()会抛InvalidOperationException且内部状态错乱导致连接永久卡死。连接池的设计哲学就是“轻量 New 重用物理连接”而非“重用 Connection 对象”。5. 开源落地实践封装一个可嵌入 WinForms 的 OracleHelper 类5.1 设计原则不造轮子只封装高频痛点我们不实现 ORM只解决 C# 工程师每天写的 5 类操作① 单条查询返回 scalar如COUNT(*)② 查询返回DataTable供 DataGridView 绑定③ 执行无返回 SQLINSERT/UPDATE/DELETE④ 执行存储过程带 IN/OUT 参数⑤ 连接字符串加密避免 config 文件明文存密码全部开源无外部依赖代码可直接复制进项目。5.2 OracleHelper 核心代码含连接字符串加密using Oracle.ManagedDataAccess.Client; using System.Security.Cryptography; using System.Text; public static class OracleHelper { private static readonly string _encryptionKey Your32ByteKeyForAes256Encryption!; // 生产环境放配置中心 // 加密连接字符串中的密码示例实际用 KMS 或 Azure Key Vault public static string EncryptPassword(string plainPassword) { using var aes Aes.Create(); aes.Key Encoding.UTF8.GetBytes(_encryptionKey.Substring(0, 32)); aes.IV new byte[16]; // 简化示例生产需随机 IV using var encryptor aes.CreateEncryptor(aes.Key, aes.IV); var encrypted encryptor.TransformFinalBlock(Encoding.UTF8.GetBytes(plainPassword), 0, plainPassword.Length); return Convert.ToBase64String(encrypted); } // 解密调用时触发 private static string DecryptPassword(string encryptedPassword) { using var aes Aes.Create(); aes.Key Encoding.UTF8.GetBytes(_encryptionKey.Substring(0, 32)); aes.IV new byte[16]; using var decryptor aes.CreateDecryptor(aes.Key, aes.IV); var decrypted decryptor.TransformFinalBlock(Convert.FromBase64String(encryptedPassword), 0, Convert.FromBase64String(encryptedPassword).Length); return Encoding.UTF8.GetString(decrypted); } // 从配置读取加密密码动态组装连接字符串 public static string BuildConnectionString(string server, string port, string service, string userId, string encryptedPassword) { var password DecryptPassword(encryptedPassword); return $User Id{userId};Password{password};Data Source{server}:{port}/{service}; } // 执行 Scalar 查询如 SELECT COUNT(*) public static object ExecuteScalar(string connStr, string sql, params OracleParameter[] parameters) { using var conn new OracleConnection(connStr); conn.Open(); using var cmd new OracleCommand(sql, conn); cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } // 查询返回 DataTableWinForms 绑定友好 public static DataTable ExecuteQuery(string connStr, string sql, params OracleParameter[] parameters) { var dt new DataTable(); using var conn new OracleConnection(connStr); conn.Open(); using var cmd new OracleCommand(sql, conn); cmd.Parameters.AddRange(parameters); using var adapter new OracleDataAdapter(cmd); adapter.Fill(dt); return dt; } // 执行非查询语句 public static int ExecuteNonQuery(string connStr, string sql, params OracleParameter[] parameters) { using var conn new OracleConnection(connStr); conn.Open(); using var cmd new OracleCommand(sql, conn); cmd.Parameters.AddRange(parameters); return cmd.ExecuteNonQuery(); } // 调用存储过程支持 OUT 参数 public static void ExecuteStoredProcedure(string connStr, string procName, params OracleParameter[] parameters) { using var conn new OracleConnection(connStr); conn.Open(); using var cmd new OracleCommand(procName, conn) { CommandType CommandType.StoredProcedure }; cmd.Parameters.AddRange(parameters); cmd.ExecuteNonQuery(); } }5.3 在 WinForms 中调用示例DataGridView 绑定// Form1.cs 中 private void LoadEmployeeData() { try { // 生产环境从 appsettings.json 读加密密码 string connStr OracleHelper.BuildConnectionString( server: 10.0.1.100, port: 1521, service: orclpdb1, userId: app_user, encryptedPassword: U2FsdGVkX1...); // AES 加密后的密码 string sql SELECT empno AS 员工编号, ename AS 姓名, sal AS 薪水 FROM emp WHERE deptno :dept; var dt OracleHelper.ExecuteQuery(connStr, sql, new OracleParameter(dept, 10)); dataGridView1.DataSource dt; // 自动绑定列名 } catch (OracleException ex) { MessageBox.Show($Oracle 错误{ex.Message}错误码{ex.Number}); } catch (Exception ex) { MessageBox.Show($未知错误{ex.Message}); } }关键设计点说明ExecuteQuery返回DataTable直接拖拽到DataGridView即可显示中文列名SQL 中AS 姓名生效所有方法staticusing无状态线程安全密码加密解密逻辑独立方便替换为 Azure Key Vault SDK只需改DecryptPassword方法OracleException单独捕获ex.Number可映射 Oracle 错误码如1017用户名密码错12541监听未启动6. 进阶技巧应对 Oracle EBS/WIP 非标工单、分页优化与字符集陷阱6.1 处理 Oracle EBS/WIP 表的特殊字段ROWID、LONG、DATE 精度EBS 中常见WIP_DISCRETE_JOBS表含ROWID物理地址、ATTRIBUTE1~15VARCHAR2(150) 但业务存 JSON、LAST_UPDATE_DATE精度到秒但业务要求毫秒。问题与解法字段类型痛点解决方案ROWIDGetOracleString()报错因 ROWID 是二进制结构用GetOracleBinary()读取后转 Base64Convert.ToBase64String(reader.GetOracleBinary(0).Value)LONG已淘汰类型但老 EBS 表仍有GetOracleString()会截断改用GetOracleLob() 流读取OracleLob lob reader.GetOracleLob(0); string text lob.Value.ToString();DATEOracle DATE 默认精度秒.NETDateTime有毫秒插入时丢失显式用OracleDbType.TimeStampcmd.Parameters.Add(new OracleParameter(last_update, OracleDbType.TimeStamp) { Value DateTime.Now });6.2 Oracle 分页为什么 ROWNUM 不能直接用于 OFFSET/LIMIT 场景EBS/WIP 查询常需“第 1001-1020 条记录”。Oracle 原生不支持OFFSET 1000 ROWS FETCH NEXT 20 ROWS ONLY12c 支持但 EBS 多跑 11g/12c。经典ROWNUM写法易翻车❌ 错误ROWNUM 1000永不成立SELECT * FROM emp WHERE ROWNUM 1000 AND ROWNUM 1020✅ 正确嵌套子查询SELECT * FROM ( SELECT a.*, ROWNUM rnum FROM ( SELECT * FROM emp ORDER BY empno ) a WHERE ROWNUM 1020 ) WHERE rnum 1000C# 封装为通用分页方法public static DataTable PaginatedQuery(string connStr, string baseSql, int skip, int take, params OracleParameter[] parameters) { string paginatedSql $ SELECT * FROM ( SELECT a.*, ROWNUM rnum FROM ( {baseSql} ) a WHERE ROWNUM :take ) WHERE rnum :skip; var allParams new ListOracleParameter(parameters); allParams.Add(new OracleParameter(skip, skip)); allParams.Add(new OracleParameter(take, take)); return OracleHelper.ExecuteQuery(connStr, paginatedSql, allParams.ToArray()); }6.3 字符集陷阱中文乱码的 3 个根源与修复现象SELECT ename FROM emp返回????。原因及对策根源检查命令修复方式客户端 NLS_LANG 未设置echo $NLS_LANGLinux或reg query HKLM\SOFTWARE\ORACLE\KEY_OraClientXXHome1 /v NLS_LANGWindows在连接字符串加UnicodeTrueUser Id...;Data Source...;UnicodeTrue;数据库字符集非 AL32UTF8SELECT * FROM nls_database_parameters WHERE parameterNLS_CHARACTERSET;若为ZHS16GBKC# 中Encoding.Default会错乱强制用 UTF8Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);连接字符串未声明字符集—在OracleConnection构造后立即执行conn.SetSessionCharset(AL32UTF8);需 ODP.NET 19.10终极建议在Program.cs入口处统一注册编码提供者并设连接字符串UnicodeTrueEncoding.RegisterProvider(CodePagesEncodingProvider.Instance); string connStr User Id...;Password...;Data Source...;UnicodeTrue;;我在线上项目踩过最深的坑是WIP 工单表WIP_ENTITIES的DESCRIPTION字段存了含 emoji 的工单备注没开UnicodeTrue导致变成??客户投诉“系统把笑脸吃掉了”。后来养成习惯——新建 Oracle 连接必加UnicodeTrue宁可多打 12 个字符不赌字符集运气。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

多语言IM源码:协议层7端互通的工程实践

多语言IM源码:协议层7端互通的工程实践

简介:这是一套面向中高级开发者与全栈工程师的多语言IM即时通讯开源学习资源,聚焦跨平台实时通信系统的设计与实现,解决多端互通、协议选型、国际化适配等核心工程问题。资源包共4个文件,含1个HTML使用说明(提供部署流…

2026/10/9 10:30:58 阅读更多 →
导师认可的技术路线图:可推演、可验证的学术逻辑闭环

导师认可的技术路线图:可推演、可验证的学术逻辑闭环

1. 什么是“导师认可的论文技术路线图”——不是画得漂亮,而是让导师一眼看懂你的思考闭环“这才是导师认可的论文 / 开题技术路线图”——这句话最近在多个高校研究生社群、学术写作训练营和导师组会复盘帖里高频出现。它不是一句空泛的夸赞,而是一次集…

2026/10/9 10:30:58 阅读更多 →
JPG、PNG、GIF、WebP、AVIF图像格式选型实战指南

JPG、PNG、GIF、WebP、AVIF图像格式选型实战指南

1. 项目概述:为什么一张图要分这么多“身份证”? 你有没有遇到过这种场景:设计师发来一张带透明背景的LOGO,你往网页上一贴,边缘却糊了一圈灰边;或者自己拍的旅行照传到社交平台后,色彩突然变得…

2026/10/9 10:30:58 阅读更多 →

最新新闻

MiniMax M Plan全模态额度统一与Claude Code、Cursor免密接入实战

MiniMax M Plan全模态额度统一与Claude Code、Cursor免密接入实战

1. 从 Token Plan 到 M Plan:额度体系到底变了什么MiniMax 把原来的 Token Plan 直接送进历史,换成了全新的 M Plan,这件事在开发者圈子里炸开锅的原因其实很简单——过去那种按 token 分档、按模态拆开计费的模式,用起来太碎了。…

2026/10/9 11:06:55 阅读更多 →
企业级AI网关实战:多模型统一接入与治理

企业级AI网关实战:多模型统一接入与治理

1. 多模型接入的乱局:为什么统一管理不是可选项 我最早接触多模型接入是在两年前,当时团队同时用着三家厂商的模型服务:一家做通用对话,一家做代码补全,还有一家专门跑长文本摘要。每个模型都有自己的控制台、自己的密…

2026/10/9 11:06:55 阅读更多 →
AI-Native组织架构设计:Agent、MCP与模型API网关落地实践

AI-Native组织架构设计:Agent、MCP与模型API网关落地实践

1. 从工具堆砌到组织重构:AI-Native 到底在说什么这两年“AI-Native”这个词被用得很泛,很多团队嘴上说着要做 AI-Native 组织,实际干的事情无非是给每个人开个模型账号、在流程里塞一个聊天窗口,然后对外宣称“我们已经全面拥抱 …

2026/10/9 11:06:55 阅读更多 →
数据库课后答案怎么用?三遍刷题法+SQLite 验证避坑指南

数据库课后答案怎么用?三遍刷题法+SQLite 验证避坑指南

简介:《数据库系统概论(第五版)》(王珊版)课后习题答案文档,专门面向学习数据库原理的本科生、考研复习者及自学者,可对照教材逐章检验理解程度。资源为单个doc文档,大小约588KB&…

2026/10/9 11:06:55 阅读更多 →
台球室预约小程序开发实战:从业务拆解到上线运营指南

台球室预约小程序开发实战:从业务拆解到上线运营指南

春节前一位开台球室的朋友找我,说要做一个台球室预约小程序。他那边35张球桌,高峰期电话不断,手写登记本翻得稀烂,散客到店经常要等一两个小时。我花了两周把整套台球室预约平台搭起来:小程序端给顾客选球台、选时段、…

2026/10/9 11:06:54 阅读更多 →
Agent-Reach:让智能体真正触达外部世界的连接方案

Agent-Reach:让智能体真正触达外部世界的连接方案

这半年我一直在折腾一件事:让AI智能体真正“连出去”。市面上不缺会写诗、会总结、会聊天的Agent,可一旦要让Agent去查报表、发通知、调外部系统,十有八九会卡住——不是模型不够聪明,而是它“够不到”。Agent-Reach这个项目&…

2026/10/9 11:05:53 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →