简介C# 增删改查代码面向正在学习 ASP.NET 与 WinForms 数据库编程的初学者以及需要快速搭建 CRUD 模板的开发者围绕 Access 与 SQL Server 两类常见数据源整理连接数据库、插入、删除、更新、查询的完整示例重点解决参数化 SQL 写法不统一、OleDb 与 SqlClient 使用易混淆等问题。压缩包仅含 1 个 doc 文档体积约 203KB以文字与代码片段集中呈现可复用的数据库操作固定模板。文档中可见 OleDbConnection、OleDbCommand、OleDbParameter、OleDbDataReader 的典型用法也包含 SqlConnection、SqlDataAdapter、DataSet 与 DataGridView 绑定数据的示例便于对照理解执行 SQL、处理参数和读取结果的关键差异。已有 821 人学习适合作为课程作业、小型管理系统开发时的速查范例也可用于梳理增删改查代码的规范结构与排错思路。1. 从一张 mdb 表和三个按钮说起去年帮一个做仓储台账的小团队修工具数据全躺在一个 db1.mdb 文件里没有服务端、没有 ORM客户的原话是「列表下面加三个按钮能加能删能改」。这种活儿最怕的不是逻辑难是不知道老项目里那套 ADO.NET 写法到底埋了多少雷。我翻到的这份 C# 增删改查源代码正好把两条最常见的路子摊开摆着一条是OleDbConnection配OleDbCommand走参数化 SQL 直连 Access另一条是SqlDataAdapter配DataSet把整表拉到内存再绑到DataGridView上做离线更新。它适合两类人一类是要在 WinForms 里快速把数据表格跑起来的新手另一类是要接手老系统、必须看懂InsertCommand和SourceVersion这套机制的人。代码不长但增删改查的骨架、参数化查询、行状态跟踪三件事全在里面。2. 技术栈与工程结构ADO.NET 两条数据通路怎么选这套代码没有任何第三方依赖纯 .NET Framework WinForms ADO.NET。听起来简单但恰恰是「纯原生」让很多人第一次跑就卡住——驱动的位数、连接字符串的写法、DataSet 的更新语义全是框架层埋着的细节。这一章先把两条通路的边界划清再落到文件职责和跑通前的环境准备。2.1 OleDb 与 SqlClient 不是换个类名那么简单原文第 2 节用的是OleDbConnection连接串长这样string path Application.StartupPath \\db1.mdb; OleDbConnection con new OleDbConnection( ProviderMicrosoft.Jet.OLEDB.4.0;Data Source path ;Persist Security InfoFalse); con.Open();这里的每个片段都有实际含义不是照抄就行Application.StartupPath指向的是 exe 所在目录调试时就是bin\Debug所以 mdb 文件必须跟着输出到那儿而不是留在项目根目录。ProviderMicrosoft.Jet.OLEDB.4.0是驱动名它决定了 .NET 走哪个 OLE DB 提供程序去读 Access。这个驱动只认.mdbAccess 2003 及更早格式新版.accdb要换成Microsoft.ACE.OLEDB.12.0。Data Source后面直接拼绝对路径注意中间不能有分号路径带空格没问题但带分号就废了。Persist Security InfoFalse表示连接打开后不再把敏感信息留在ConnectionString属性里。本地 mdb 没有密码这行写了也无害属于模板习惯。原文第 3 节换成了SqlConnection连接串是一个常量private const string DRIVER server.;databasedemo;uidsa;pwdsa; private const string sql_select select * from region;server.是「本机默认实例」的简写uid/pwd直接用 sa 账号。这种方式在今天看当然不合格但它反映的是那个年代局域网小工具的主流做法账号写死、库名写死、连接不加密。两条通路的差别远不止类名落到代码上差别很大维度OleDbAccessSqlClientSQL Server连接对象OleDbConnectionSqlConnection命令对象OleDbCommandSqlCommand参数对象OleDbParameterSqlParameter参数占位符?或name但按位置匹配name按名字匹配是否支持 DataAdapter 批量更新支持但行为受限完整支持典型场景单机小工具、老系统、单文件数据库局域网/服务端应用最关键的一行是「按位置匹配」。OleDb 虽然允许你在 SQL 里写a、b但它底层用的是 OLE DB 的位置占位符Parameters.Add的顺序必须和 SQL 里出现的顺序严格一致你写成b在前、a在后参数值就会悄悄错位——不报错数据就是错的。这一点是后面避坑章节里最容易被忽略的一条。2.2 文件职责划分一个 Form 里到底塞了什么原文第 3 节的Form1把几乎所有东西放在了一个类里。这种写法被骂了很多年但你要接手就得先认清它的结构。按原文还原工程里实际起作用的文件大致是这几类文件职责说明Form1.cs全部业务逻辑连接、SQL 常量、增删改方法、按钮事件都在这儿Form1.Designer.cs控件声明与布局dataGridView1、button1~3由设计器生成不要手改App.config配置项原文没用上连接串是写死在常量里的bin\Debug\db1.mdb数据文件StartupPath指向这里缺了必崩bin\Debug\*.exe输出平台目标决定它是 32 位还是 64 位进程Form1顶部有三个字段和两个常量这是整章的主干private DataSet ds new DataSet(); // 内存中的离线数据容器 private SqlConnection conn null; // 连接对象在 Load 里初始化 private SqlDataAdapter da null; // 适配器负责 Fill 和 Update private const string DRIVER server.;databasedemo;uidsa;pwdsa; private const string sql_select select * from region;字段声明成类级别而不是方法内的局部变量是因为Fill和Update发生在不同的方法里必须共享同一个ds和da。这就是 DataSet 路线的核心特征数据在内存里活着数据库连接只在 Fill 和 Update 那两个瞬间存在。理解这一点后面AcceptChanges和SourceVersion的行为就都能推出来了。2.3 跑通前的环境准备原文给的代码片段是不完整的有些行号混进了源码比如da.InsertCommand 8conn.CreateCommand();里的8明显是行号粘连直接复制粘贴编译不过。要跑起来先把下面四件事做掉。第一建表。示例库里的region表只有两列自己建一份等价结构即可-- 与原文 region 表等价的最小结构 CREATE TABLE region ( regionid INT NOT NULL PRIMARY KEY, -- 主键更新/删除时作为定位条件 regiondescription VARCHAR(50) NULL -- 描述文本界面上可编辑 );主键这一行不能省。SqlDataAdapter的删除和更新命令里用SourceVersion.Original去取原始值没有主键或者主键没被正确识别Update会直接抛「对于不返回任何键列信息的 UpdateCommand动态 SQL 生成无效」。第二把 mdb 或建表脚本跟输出目录对齐。Access 方案要把db1.mdb的「复制到输出目录」设成「如果较新则复制」否则每次清理重建都会丢文件SQL Server 方案不用拷文件但要确认本机实例名和server.对得上。第三把平台目标从AnyCPU改成x86。Microsoft.Jet.OLEDB.4.0只有 32 位版本64 位进程加载它会直接抛「未在本地计算机上注册」。这一条后面还会展开。第四如果坚持用 DataSet 路线Form1_Load里必须有da.Fill(ds, table)这一句且表名table和后面ds.Tables[table]的字符串必须一模一样——这是硬编码字符串最容易翻车的地方。提示先只跑查询把dataGridView1刷出数据来再去接增删改。查询通了说明连接串、驱动、表结构三件事都对剩下的都是逻辑问题。3. 核心链路拆解一次「增」从按钮点击到 ExecuteNonQuery这一章按调用顺序拆。原文其实混了两套写法前半段是「每次操作新建连接 参数化 SQL」后半段是「共享连接 DataAdapter 批量更新」。两者的链路完全不同混着看会懵所以要分开讲。3.1 固定模板直连模式的六个步骤原文第 2 节的增删改查都遵循同一个骨架我把它整理成可复用的模板// 步骤 1拼连接串路径来自 exe 所在目录 string path Application.StartupPath \\db1.mdb; string connStr ProviderMicrosoft.Jet.OLEDB.4.0;Data Source path ;Persist Security InfoFalse; // 步骤 2开连接用 using 保证一定释放 using (OleDbConnection con new OleDbConnection(connStr)) { con.Open(); // 步骤 3写带占位符的 SQL绝不拼字符串 string sql insert into t1(name, pwd) values (a, b); // 步骤 4建命令对象绑定连接 using (OleDbCommand com new OleDbCommand(sql, con)) { // 步骤 5按 SQL 中出现顺序追加参数 com.Parameters.Add(new OleDbParameter(a, textBox1.Text)); com.Parameters.Add(new OleDbParameter(b, textBox2.Text)); // 步骤 6执行返回受影响行数 int rows com.ExecuteNonQuery(); } }逐段说明using包裹连接和命令是这套模板里唯一比原文更值得坚持的改动。原文写的是con.Open()之后一路往下走异常一抛连接就泄漏mdb 文件会被进程锁住第二次打开直接报「文件已在使用中」。SQL 里的a、b是占位符不是字符串替换。参数化查询把值和语句分开传给数据库输入 or 11 --也只会被当成一个普通字符串这是防注入的根本手段。OleDbParameter(a, textBox1.Text)的第二个参数是object类型传字符串进去会被推断成VarChar。如果目标列是intAccess 一般能隐式转换但遇到空字符串会抛「类型不匹配」此时应显式写new OleDbParameter(a, OleDbType.Integer) { Value int.Parse(...) }。ExecuteNonQuery()返回受影响的行数。增删改都用它返回 0 说明条件没命中比如删了一条不存在的记录不是异常。3.2 增删改三段 SQL 的差异点原文给的三个语句值得逐个对照看差异都藏在细节里。// 增列名和占位符一一对应 string sql insert into t1(name, pwd) values (a, b); // 删只按 name 定位pwd 不参与 string sql delete from t1 where name a; // 改a 是新值b 是定位条件顺序不能反 string sql update t1 set pwd a where name b;参数绑定的部分完全一样都是「建OleDbCommand→Parameters.Add→ExecuteNonQuery」。真正的坑在两处一是update语句里a和b的语义不同一个是新值一个是条件值。原文对应的是textBox1是新密码、textBox2是用户名。你如果照抄时把两个 TextBox 搞反代码不会报错只会把所有人的密码改成用户名。这种错误在测试环境里很难被发现上线才发现数据已经被写花了。二是delete from t1 where name a以name作为唯一条件。如果name上没有唯一索引一条 DELETE 可能删掉多行。原文的场景是登录表name大概率是唯一的但代码本身没有做任何约束保护。真要落到生产条件应该补上主键// 更安全的删除用主键定位避免同名多删 string sql delete from t1 where id id; com.Parameters.Add(new OleDbParameter(id, OleDbType.Integer) { Value userId });3.3 查询分支ExecuteReader 和前三者的本质区别原文特意在查询那段加了注释「与前三者不同」这个提醒是对的string sql select * from t2 where Name a and Pwd b; using (OleDbCommand com new OleDbCommand(sql, con)) { com.Parameters.Add(new OleDbParameter(a, textBox1.Text)); com.Parameters.Add(new OleDbParameter(b, textBox2.Text)); using (OleDbDataReader dr com.ExecuteReader()) // 返回的是游标不是行数 { if (dr.Read()) // 有数据返回 true并把游标推到第一行 { MessageBox.Show(登录通过); } else { MessageBox.Show(用户名或密码不正确); } } }这里三个点必须讲清楚ExecuteReader()返回OleDbDataReader它是一个只进只读的流式游标连接不关它就一直占着。所以必须用using包住或者显式dr.Close()。dr.Read()返回bool有下一行就返回true并把当前行指针前移。判断「查到了没有」用它不要用dr.HasRows之外的任何属性去猜。登录场景只需要「存在性判断」所以if (dr.Read())足够。如果要多行遍历写成while (dr.Read()) { var name dr[name]; }列名大小写不敏感但拼错会抛IndexOutOfRangeException。顺带说一句原文这段 SQL 是把用户名和密码一起丢进 WHERE 里比对属于明文密码时代的写法。真要改成现在的做法应该是「按 name 查出密码哈希 → 在代码里校验」而不是让数据库替你判断。3.4 DataSet 路线Fill 与 Update 的分工原文第 3 节是另一套思路用的是断开式数据集private void Form1_Load(object sender, EventArgs e) { conn new SqlConnection(DRIVER); // 只创建不 Open da new SqlDataAdapter(sql_select, conn); // 适配器持有查询语句 da.Fill(ds, table); // 内部自动 Open/Close this.dataGridView1.DataSource ds.Tables[table].DefaultView; }SqlDataAdapter.Fill的行为值得单独记一笔它会在内部打开连接、执行查询、把结果灌进DataSet的指定表、然后自动关闭连接。所以外面不需要conn.Open()写了反而多余不报错但语义混乱。更新则靠三个命令对象private bool BtnInsert() { da.InsertCommand conn.CreateCommand(); da.InsertCommand.CommandText insert into region values(id, ption); // 第 2、3 个参数分别是类型和长度第 4 个是 DataTable 里的源列名 da.InsertCommand.Parameters.Add(id, SqlDbType.Int, 4, regionid); da.InsertCommand.Parameters.Add(ption, SqlDbType.VarChar, 10, regiondescription); int count da.Update(ds); // 把 ds 里的变更回写到数据库 return count 0; }Parameters.Add(name, type, size, sourceColumn)这个四参数重载是 DataAdapter 路线的灵魂最后一个参数sourceColumn告诉适配器「这个 SQL 参数的值从 DataTable 的哪一列取」。有了它da.Update(ds)才能自动把新增行的列值映射到 INSERT 语句里。insert into region values(id, ption)这句还有个小前提省略列名时VALUES里的顺序必须和表定义的列顺序完全一致。region表只有两列所以没事换成多列表就是典型翻车点稳妥写法是显式列出列名。4. 界面到数据的对齐DataGridView 绑定与参数源映射前一章讲的是「怎么执行」这一章讲「界面上的操作怎么变成数据库里的变更」。DataGridView 加 DataSet 这套组合的出问题概率远高于单纯写 SQL原因是中间隔了一层行状态跟踪。4.1 Fill 之后绑的是 DefaultView 还是表原文这一行this.dataGridView1.DataSource ds.Tables[table].DefaultView;绑的是DefaultView而不是DataTable本身。两者在只读展示时没区别但在编辑场景下有实际差异DefaultView支持排序和筛选RowFilter、Sort你在界面上点列头排序改的就是这个视图如果直接把DataTable赋给DataSourceWinForms 内部也会包一层默认视图效果类似但拿不到引用。Fill(ds, table)里的第二个参数是表名必须和ds.Tables[table]严格一致。这个字符串是硬编码的改了这边忘了那边运行时报「未将对象引用设置到对象的实例」因为ds.Tables[table]返回 null。如果想让改动更直观可以在 Fill 之后立刻关掉自动生成列da.Fill(ds, table); dataGridView1.AutoGenerateColumns true; // 默认就是 true列按 DataTable 结构生成 dataGridView1.DataSource ds.Tables[table].DefaultView;4.2 三个 Command 的参数源映射与 SourceVersion 玄学原文的删除方法里有一行很关键private bool BtnDelete() { SqlParameter sp new SqlParameter(); da.DeleteCommand conn.CreateCommand(); da.DeleteCommand.CommandText delete from region where regionid id; sp da.DeleteCommand.Parameters.Add(id, SqlDbType.Int, 4, regionid); sp.SourceVersion DataRowVersion.Original; // 取「改之前」的值 ds.Tables[table].Rows[dataGridView1.CurrentRow.Index].Delete(); int count da.Update(ds); return count 0; }SourceVersion这个属性是 DataAdapter 路线上最容易出玄学的地方。DataRow同时保存多个版本Current当前值、Original从数据库读出来时的值、Proposed编辑中还没提交的值。删除和更新要用哪个删除用Original。因为行已经被标记为Deleted它的Current值已经不可靠唯一能定位数据库记录的只有原始主键。更新SET后面的新值用CurrentWHERE后面的定位条件用Original。原文的更新方法正是这么写的da.UpdateCommand.CommandText update region set regionidid, regiondescriptionption where regionidoldid; da.UpdateCommand.Parameters.Add(id, SqlDbType.Int, 4, regionid); da.UpdateCommand.Parameters.Add(ption, SqlDbType.VarChar, 10, regiondescription); SqlParameter sp da.UpdateCommand.Parameters.Add(oldid, SqlDbType.Int, 4, regionid); sp.SourceVersion DataRowVersion.Original; // 用旧主键定位注意id和oldid映射的是同一个源列regionid区别只在SourceVersion。这就是「主键被修改时仍能正确更新」的标准写法。不加SourceVersion.Original一旦用户改了主键列WHERE就会用新值去匹配结果是一条都更新不到Update返回 0界面上提示「修改失败」你还以为是数据库连不上。还有一个隐含条件da.UpdateCommand、da.DeleteCommand必须在使用前赋值且ds里确实存在对应的行状态。如果用户在 DataGridView 里根本没动过任何单元格ds中所有行的RowState都是UnchangedUpdate会返回 0不是出错。4.3 CurrentRow、行索引与刷新时机删除方法用了dataGridView1.CurrentRow.Index来定位行ds.Tables[table].Rows[dataGridView1.CurrentRow.Index].Delete();这行有两个前提条件缺一个就抛异常或删错行第一CurrentRow不能为 null。当表格没有选中行、或者AllowUserToAddRows true且光标停在最后那行「新建行」上时CurrentRow可能指向新行或为 nullIndex直接抛NullReferenceException。稳妥写法是先判空if (dataGridView1.CurrentRow null || dataGridView1.CurrentRow.IsNewRow) { MessageBox.Show(请先选中一行); return false; }第二Rows[Index]的索引要和 DataGridView 的显示索引对齐。如果中间做过排序点了列头DataGridView的CurrentRow.Index是显示索引而DataTable.Rows的索引是原始索引两者会错位删掉的就是别的行。这也是「点删除删错了数据」这类问题最常见的成因。正确做法是从绑定的数据对象反查var rowView dataGridView1.CurrentRow.DataBoundItem as DataRowView; if (rowView ! null) { rowView.Row.Delete(); // 直接拿到对应的 DataRow绕开索引映射 }至于刷新原文的流程是「先 Delete 标记 → 再 Update 落库」但没有重新 Fill。所以删除成功后 DataGridView 上那行还在只是被隐藏了Delete()会把行标记为Deleted绑定视图默认过滤掉。想让界面立刻反映真实状态Update之后要么ds.AcceptChanges()要么重新da.Fill(ds, table)。前者清掉所有行状态后续无法再 Update 这些行后者会重查一遍数据库。我一般选后者多一次查询换来状态干净。5. 避坑与排查五条踩过的坑这套代码看起来直白实际跑起来翻车的地方集中在驱动、参数顺序和行状态三块。下面五条是我和同事真实碰到过的按「现象 → 原因 → 解决」写。5.1 报「未在本地计算机上注册 Microsoft.Jet.OLEDB.4.0 提供程序」现象编译通过一运行到new OleDbConnection(...)就抛异常换台机器又能跑。原因Microsoft.Jet.OLEDB.4.0只有 32 位版本而项目默认平台目标是AnyCPU。在 64 位系统上AnyCPU会让进程以 64 位启动加载 32 位驱动必然失败。开发机上装过完整 Office 的话可能恰好有 32 位运行时被别的宿主进程带起来造成「我这能跑」的假象。解决项目属性 → 生成 → 平台目标改成x86强制进程以 32 位运行。或者改用Microsoft.ACE.OLEDB.12.0并安装对应位数的数据库引擎同时连接串里的 Provider 一起换掉。别去改连接串硬拼驱动缺失不是字符串能解决的。5.2 更新成功但数据没变或者改错了行现象点修改按钮弹出「修改成功」去数据库里一查值还是旧的有时候干脆改成了另一个人的数据。原因OleDb的参数是按位置匹配的不是按名字。SQL 里写的是set pwda where nameb如果Parameters.Add的顺序反了a拿到的就是用户名b拿到的才是密码。因为两者都是字符串类型数据库不会报类型错误直接执行成功。解决养成「SQL 里占位符出现的顺序 参数 Add 的顺序」这个硬约束写完对着数一遍。更稳的做法是给每个参数显式指定名字并在 SQL 里保持同名同序同时在测试库里先手动执行一遍等价 SQL 校验结果。5.3 删除报错「对于不返回任何键列信息的 UpdateCommand动态 SQL 生成无效」现象da.Update(ds)抛InvalidOperationException提示缺少 UpdateCommand 或者键列信息。原因SqlDataAdapter在没有显式配置DeleteCommand的情况下会尝试自动生成命令但它需要从SELECT语句里推断主键。原文的sql_select是select * from region如果表上没定义主键或者Fill之后DataTable的PrimaryKey为空推断就失败。解决两条路选一条。一是像原文那样显式赋值da.DeleteCommand / UpdateCommand / InsertCommand不要依赖自动生成二是给DataTable手动设主键ds.Tables[table].PrimaryKey new DataColumn[] { ds.Tables[table].Columns[regionid] };显式配置更可控尤其是表有自增列或复合主键的时候自动生成的 SQL 经常不合预期。5.4 mdb 文件被占用第二次打开报「文件已在使用中」现象第一次操作正常关掉窗口再打开或者同时开两个实例就报文件被锁定。原因OleDbConnection没有Close/Dispose。原文的连接是在方法里new出来直接Open的异常一抛就跳过了后面的关闭逻辑连接对象挂在 GC 队列里文件句柄一直不释放。解决所有连接、命令、Reader 一律using包裹异常路径也能保证释放。另外注意OleDbDataReader不关的话连接也关不掉必须嵌套using或者先dr.Close()再con.Close()。5.5 界面改了单元格点修改没反应现象在 DataGridView 里把某行描述改掉点修改按钮提示「修改失败」程序不报错。原因da.Update(ds)依赖DataRow.RowState判断该执行哪条命令。如果用户还在编辑状态没离开单元格改动还没提交到DataRowRowState仍然是UnchangedUpdate扫一遍发现没变更返回 0。另外如果在修改前调用过ds.AcceptChanges()所有行的状态会被重置成Unchanged、Original也被覆盖后续再怎么改都找不到原始值。解决执行前先dataGridView1.EndEdit()强制提交当前编辑AcceptChanges只在确认落库成功之后调用别在Fill之后顺手加一句。原文的BtnUpdate里就没调AcceptChanges这个细节是对的。6. 二次开发把散在事件里的 SQL 收成一层可替换的数据访问这份代码最该改的地方不是语法是结构SQL 字符串散落在每个button_Click里连接串写死在常量里OleDb和SqlClient各写一套。真要做二次开发第一步是把数据访问抽出来让界面只关心「调什么」不关心「怎么连」。我会先定一个最小接口只暴露四个方法public interface IRegionRepository { DataTable GetAll(); // 查询返回离线表供 DataGridView 绑定 bool Insert(int id, string desc); // 增返回是否成功 bool Update(int id, string desc); // 改 bool Delete(int id); // 删 }然后按数据库类型落两个实现OleDbRegionRepository和SqlRegionRepository内部的 SQL 和参数绑法沿用前面拆解过的那套模板只是把using补上、把连接串挪到App.config的connectionStrings里。界面层只认接口注入哪个实现在启动时决定IRegionRepository repo new SqlRegionRepository( ConfigurationManager.ConnectionStrings[main].ConnectionString); dataGridView1.DataSource repo.GetAll();这么改完有三个直接收益换数据库只改一行实例化SQL 集中在一处加日志和计时不用满项目找单元测试可以直接对一个内存实现跑不依赖真实库。验证方式我通常分三步走先拿查询接口刷出表格确认数据通路没问题再用一个固定的主键跑增、改、删、再查看四次结果是否闭环最后把连接串故意改错一次确认异常被捕获并弹了提示而不是让进程直接崩掉。第三步最容易被跳过但它决定了工具拿到客户现场会不会一句话都说不出来。有个细节值得单独提醒如果继续走 DataSet 路线RowState和SourceVersion那套语义不会因为你抽了接口就消失Update前后仍然要保证「先EndEdit、后Update、最后AcceptChanges」的顺序。我早年图省事在Fill后面顺手加过一句ds.AcceptChanges()结果整个修改功能静默失效查了两个小时才定位到那一行。从那以后我每次动 DataSet都强制在Update之后才写AcceptChanges并且在测试库里手动执行一遍等价 SQL 对数。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
解决IIS Express启动报错:网络名格式无效(0x800704be) 1. 问题现象与背景分析 最近在调试一个基于.NET Core 3.1的Web API项目时,遇到了一个棘手的IIS Express启动报错:"application "/". Error description: 指定的网络名格式无效。(0x800704be)"。这个错误发生在Visual Studio 2019中按… · 2026/11/3 22:37:16
深入解析ACPI MADT表与APIC中断机制 1. MADT表概述与核心结构解析多APIC描述表(Multiple APIC Description Table,简称MADT)是ACPI规范中用于描述系统中断控制器架构的关键数据结构。在支持APIC(Advanced Programmable Interrupt Controller)或SAPIC&… · 2026/11/3 19:53:19
嵌入式方向可视化组件:雷达图+摇杆图双模态实时渲染 简介:这是一份基于Qt5.15.2与VS2019开发的轻量级C图形控件实现资源,面向具备基础C和Qt开发经验的中级学习者,用于快速集成雷达图与可扩展方向的摇杆图(rocking bar)到自定义界面中。资源不含第三方依赖,采用… · 2026/11/3 19:55:12
uniapp海外游戏分发工程:PG电子集成与Switch卡带区域适配 简介:这是一套面向海外游戏业务开发者的全栈前端解决方案,基于UniApp框架实现跨平台兼容,专为构建海外游戏交易平台、手游下载站及Switch游戏卡带销售系统设计。资源包含完整可二次开发的前端源码(非编译后产物)&#… · 2026/11/4 0:00:17
Qoder NEXT:智能代码补全工具的技术解析与应用 1. 项目概述Qoder NEXT作为新一代智能编程辅助工具,其核心突破在于通过深度优化代码补全算法,将AI生成代码的开发者采纳率提升了65%。这个数字背后代表着编程效率的实质性飞跃——开发者不再需要花费大量时间在重复性代码编写和机械性调试上,… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46