本页列出把老项目升到当前框架(4.0.0 / .NET 10)时最常见的改动点。升级动作本身(备份、重编、跑测试)见版本与升级指引;这里聚焦"代码会因哪些结构调整而报错,怎么改"。每条都以编译器报错为触发点——先升引用、全量重编,让红线自己浮出来,再照着下表修,不要盲改。
迁移步骤(推荐顺序)
- 干净工作区 + 备份(版本控制下即可)。
- 更新被引用的
Known框架程序集,全解决方案重编。 - 按编译错误归类到下面的"迁移点",逐类批量处理。
- Release 配置清到 0 error / 0 warning。
- 三种运行形态各起一次,回归核心业务与登录;核对
EnsureSchemaAsync的schema.Warnings无破坏。
常见迁移点
命名空间与装配门面归并。早期的服务扩展曾散在 Known.Services,现已并入 Known.Platforms——SaveConfigAsync / ExistsConfigAsync / GetConfigAsync 这些键值配置扩展都挂在 Known.Platforms.ConfigExtension 上。老代码里 using Known.Services; 改 using Known.Platforms; 即可。
鉴权契约收敛。IAuthProvider 不再只管登录,还负责装配可见菜单,新增了两个成员:
List<MenuItem> BuildMenus(UserInfo user); // 侧边栏
List<MenuItem> BuildAppMenus(UserInfo user); // 移动端底部 Tab
若你有自定义 provider,别再实现裸接口,改为继承框架默认实现 AuthProvider 基类,只需覆写鉴权四件套(IsAuthenticated / GetUserAsync / SignInAsync / SignOutAsync),菜单装配从基类白送——Web 的 CookieAuthProvider : AuthProvider 正是这个写法。
自动建表回来了。schema 同步能力在某个大版本一度缺位,4.0 已补回:启动时 UseDatabase(...) 会调 EnsureSchemaAsync 按实体做非破坏性建表 / 增列。老项目若此前靠自己手写建库脚本,可以逐步交还给框架,但注意红线——它只加不删,删列 / 改类型仍需你显式迁移。
主键与外键类型。统一按 string(varchar(50))存 GUID,不要用 Guid 类型,也别忘了 EntityBase.Id 带 [Key]。老库里若曾把 Id 建成整型或 uniqueidentifier,迁移时要显式对齐(这一步不自动,务必先备份)。
组件基类的服务注入与释放。BaseComponent 已内置 [Inject] LocalService Local,并在 OnInitializedAsync 自动订阅 Local.Changed、Dispose 里退订。两个连带约束:
- 继承
BaseComponent的组件若你自己新增了Dispose(),必须写成public override void Dispose() { ...; base.Dispose(); },漏掉base.Dispose()会 CS0114 并泄漏回调。 - 直接继承
ComponentBase/LayoutComponentBase的页面 / 布局(Page*、Layout)要自己加@inject LocalService Local,才能用Local。
标记列(新增写法,旧写法不变)。列表参数仍是 Columns,Table<TItem> 另多了一个列插槽 ChildContent:把 <Column> 直接写在 <Table> 里即成标记列,<Table TItem="Order"><Column TItem="Order" Title="编号" Field="Id" /></Table>。标记列是泛型组件,TItem 要和所属表格一致、逐列写明(Razor 只按同一个元素上的属性值推断类型参数,单元格模板推不出 TItem,省略即 CS0411;把列插槽写成 RenderFragment<TItem> 也绕不开——登记列时还没有「当前行」,还会和列自己的隐式 context 撞名 RZ9999);单元格模板直接写在列里,里面的 context 就是强类型当前行,不再需要 RenderTreeBuilder 手写。分组表头把子列写进本列的 <Columns>。既有 Columns="@columns" 一行都不用改,标记列与列表列可混用、列表列在前;SelectTable 的 Columns 未受影响。三个 Razor 约束记牢:条件列给 Visible(用 @if 包裹会让重新挂载的列登记到末尾而不是回到原位);同一列上不能既写列内容又写 <Header> 这类具名片段(RZ9996),两者都要时把单元格收进 <ChildContent Context="row">;表格里裸写列时不能再出现 <RowActions> 这类具名片段,要混用就把列包进 <ChildContent>。
装配入口与基地址。入口固定为 AddKnown + 形态入口(AddKnownClient / AddKnownWeb / AddKnownDesktop),并推荐把它们收进你自己的 AddMyApp(AppType) 封装(开源示例名 AddKnownApp)。AppType 只有 { Web, Desktop }。WASM 客户端基地址用 HostEnvironment.BaseAddress(站点根),不要再手动拼 + "api"。Config.AddModule(业务程序集) 必须排在 AddKnown 之后,业务 [Service] 实现才覆盖得到默认。
国际化写法。用户可见文本一律走 Local:字面量 @Local["中文"]、变量渲染 @Local[Param]、属性字面量 title='@Local["中文"]'。带插值的句子用具名占位符:@Local.Format("共 {count} 条 · 第 {page} / {pages} 页", new { count, page, pages })——旧的 {0} 位置参数写法要改成 {name},模板键里的 {name} 由匿名对象同名属性代入。词条按语言 code 幂等合并、后者覆盖前者,页面译文放其所属程序集的 wwwroot/i18n/{tag}.json,别塞进框架包。
其它高频 Razor / 控件坑(升级时编译器或运行期容易撞上):Select 的候选 Value 一律按 string 处理;不要重复声明基类已有的 Class / Style / Disabled(否则 CS0108);Icon 无匹配时回退 circle;UIService.Safe 只接 Func<ValueTask>,需拿返回值就直接 try/catch 调 InvokeAsync<T>。
迁移后自检
改完对照API 一览核对签名、对照全表核对默认值(尤其 Visible 默认是 true)。跑一遍三形态冒烟 + Release 零警告,就可以把这次迁移归档、更新你自己的升级笔记了。若某条迁移点在文档里说不清,欢迎反馈补全。
扫码关注公众号
扫码加入 QQ 群