☰
基于C# ASP.NET MVC的固定资产管理系统设计与实现
2026/10/26 7:28:46 网站建设 项目流程

简介:面向企业资产管理与.NET开发学习者的固定资产管理系统完整源码包,采用C#与SQL Server 2005构建,基于ASP.NET Web三层架构,覆盖资产登记、折旧计算、盘点、维修、报废及报表统计等核心业务模块,适合作为毕业设计、课程实训或企业信息化项目参考。压缩包共112个文件,包含42个C#源码文件、41个ASPX页面、15个SQL脚本,以及MDF/LDF数据库文件、站点地图、母版页和配置文件,可据此还原数据库并部署运行,2.85MB的体积便于快速下载。已有252人学习。利用这套代码,开发者能直观理解表示层、业务逻辑层与数据访问层的协作方式,掌握用户登录权限控制、资产全生命周期管理及报表生成等关键实现;配套的示例数据库和页面截图,也有助于对照前端界面调试后端逻辑,是提升Web开发与数据库设计能力的实战素材。

1. 项目整体设计与技术选型

1.1 为什么固定资产管理系统必须走 Web 化

干了这么多年企业信息化相关项目,我越来越觉得固定资产管理是最适合先做 Web 化的内部系统之一。很多公司还在用 Excel 管理资产,资产编号、存放地点、使用人、采购日期全靠手工维护,碰上资产盘点或者部门调整,光是核对台账就能耗掉一个行政人员好几天。

固定资产管理系统的核心需求其实很朴素:资产从入库、领用、归还、调拨到维修、报废,全生命周期要有记录;账实要相符;权限要清晰——普通员工只能看自己名下的资产,部门主管要看本部门台账,资产管理员才能做入库和处置操作。基于 Web 的方案天然适合这个场景,浏览器访问、免安装客户端、多部门并发操作、权限集中控制,这些优势是当年 C/S 架构做不到的。C# 在这个领域又特别合适,生态成熟,做企业管理类系统效率高,所以选型上几乎没有悬念。

1.2 技术选型背后的思考过程

我把这套系统定位为“企业内部工具型系统”,追求的是开发效率、部署简便和维护成本低,所以技术栈选得比较务实:

后端:C# + ASP.NET MVC + Entity Framework
数据库:SQL Server(Express 版本也够用)
前端:LayUI + jQuery + 原生 HTML
报表导出:NPOI(Excel 导入导出)
条码生成:ZXing.Net(生成资产标签二维码)

用 ASP.NET MVC 而不是 WebForm,是因为 MVC 前后端分离更彻底,视图逻辑不掺杂在后台代码里,后期接移动端或者做接口扩展都方便。EF 做数据访问直接操作实体类,开发速度比手写 ADO.NET 快得多。前端选 LayUI 而不是 Vue 或 React,是因为这类后台管理页面主要就是表格、表单、弹窗三件套,LayUI 的组件风格统一,不用额外搭脚手架,一个人开发也不至于被前端工程化拖垮。

这套组合照顾了不同水平的读者:刚入门的可以照着 MVC 的管道流程理解请求处理;有经验的可以在权限模块和库存一致性上做扩展。整个项目结构遵循经典的三层架构:表现层(Controllers + Views)、业务逻辑层(Services)、数据访问层(Repositories + EF DbContext),各层职责单一,出了问题也好排查。

2. 数据库设计与核心模块拆分

2.1 数据表设计要覆盖哪些业务动作

做资产管理系统,最忌讳把表设计成一张“大宽表”,什么字段都往里塞。我在设计时用了“主表 + 流水表”组合:主表管资产当前状态,流水表管每一次操作记录。这样做的好处是,想看某台笔记本的完整履历,直接按资产编号查流水表就行,不用去翻操作日志。

核心表结构如下:

  • Asset(资产主表):资产编号、资产名称、分类、规格型号、购置日期、原值、当前使用人、存放地点、状态、备注
  • AssetCategory(分类表):办公设备、IT设备、家具、车辆等分类层级
  • Department(部门表):部门名称、负责人
  • Employee(员工表):工号、姓名、所属部门、手机号
  • AssetRecord(资产流水表):资产编号、操作类型(入库/领用/归还/调拨/维修/报废)、操作人、操作时间、备注
  • RepairRecord(维修记录表):故障描述、维修商、费用、维修日期、完成日期
  • SysUser(系统用户表):登录账号、密码哈希、用户姓名、角色
  • SysRole(角色表):管理员、资产专员、部门主管、普通员工

资产编号我建议按“分类代码-年份-序号”组合,比如 BG-2024-0001 表示 2024 年登记的第 1 台办公类资产,这样从编号就能大概判断资产类型和登记时间,后期盘点核对也方便。

2.2 权限模型与登录会话处理

权限这块我用的是最简单的 RBAC 模型,三个核心角色足以覆盖大部分企业的管理流程。普通员工登录后只能查自己的资产和提交借用申请;部门主管多一个导出本部门台账的权限;资产管理员则拥有全部操作权限,包括资产入库、报废审批、盘点录入。

密码存储必须做哈希,我用的方式是加盐的 SHA256,千万不能明文存库,这是底线。用户登录成功后将用户 ID、姓名、角色存到 Session 里,在 MVC 的基类控制器中重写 OnActionExecuting 方法做权限校验,或者直接给需要权限的 Controller 打上自定义 AuthorizeAttribute 特性。这样权限逻辑集中在过滤器里,不会散落在各个方法中。

注意:Session 的过期时间建议设成 20 分钟,资产管理系统里经常有录到一半去查资料的情况,时间太短容易丢数据,Action 里要养成把表单草稿临时存 TempData 的习惯。

2.3 数据库设计的数据一致性考量

资产状态和流水记录的同步必须放在一个数据库事务里。比如“领用”操作,既要更新 Asset 表的使用人、状态字段,又要插入一条领用流水,这两步如果拆开执行,系统崩溃时就会出现“资产显示未领用但流水已经生成”的脏数据。

库存单价、折旧金额等数值字段,数据库里我用 decimal 而不是 float,避免浮点数计算误差。所有表都加上 CreateTime、UpdateTime 两个通用字段,后续排查数据问题会省很多事。索引方面,AssetRecord 表按 AssetId 建索引,因为查询资产履历是最常见的操作。

3. 核心功能实现与关键代码解析

3.1 资产入库到报废的完整生命周期

固定资产管理的核心逻辑就是一个字:转。资产从供应商到公司仓库是入库,从仓库到员工手里是领用,员工离职或部门调整是归还和调拨,设备坏了是维修,彻底不能用了是报废。每个环节在系统里都对应一个状态变更,我把状态设计成常量枚举,避免魔法数字散落在代码里。

资产状态流转图如下(用表格描述):

状态名称触发操作允许流转到的状态
在库入库登记领用
在用领用归还、调拨、维修
维修中申请维修在用、报废
已报废报废审批无

核心的领用操作我用三层结构来实现,Controller 只负责参数接收和返回视图,Service 层处理业务校验,Repository 层操作数据库。领用操作的核心代码如下:

public ResultData BorrowAsset(int assetId, int employeeId, string remark) { using (var transaction = _db.Database.BeginTransaction()) { try { var asset = _db.Assets.FirstOrDefault(a => a.Id == assetId); if (asset == null) return ResultData.Error("资产不存在"); if (asset.Status != AssetStatus.InStock && asset.Status != AssetStatus.Returned) return ResultData.Error("当前资产状态不允许领用"); asset.Status = AssetStatus.InUse; asset.CurrentUserId = employeeId; asset.OperateTime = DateTime.Now; _db.AssetRecords.Add(new AssetRecord { AssetId = asset.Id, OperateType = OperateType.Borrow, OperatorId = CurrentUserId(), OperateTime = DateTime.Now, Remark = remark }); _db.SaveChanges(); transaction.Commit(); return ResultData.Success(); } catch (Exception ex) { transaction.Rollback(); return ResultData.Error("操作失败:" + ex.Message); } } }

这段代码看着简单,但有几个关键点一定要说清楚:第一,查询资产后立刻检查状态,这是防止两个用户同时申请同一台设备的并发问题;第二,更新主表和插入流水放在同一个事务里,谁也别想单独成功;第三,操作人从当前登录会话里取,不能从前端传,否则任何人都可以伪造操作人。

3.2 盘点模块与 Excel 导入导出

资产盘点功能是行政和财务部门最依赖的模块,盘点流程是:发布盘点任务,打印盘点表或导出 Excel,线下对照实物逐项勾选,最后把结果回传系统,系统自动比对账实差异。

导出台账我用 NPOI 实现,代码清晰而且不需要服务器安装 Office:

public MemoryStream ExportAssetList() { var assets = _db.Assets.Include(a => a.Category).Include(a => a.CurrentEmployee).ToList(); var workbook = new XSSFWorkbook(); var sheet = workbook.CreateSheet("固定资产台账"); var header = sheet.CreateRow(0); string[] columns = { "资产编号", "资产名称", "分类", "使用人", "存放地点", "状态", "购置日期", "原值" }; for (int i = 0; i < columns.Length; i++) header.CreateCell(i).SetCellValue(columns[i]); int rowIndex = 1; foreach (var asset in assets) { var row = sheet.CreateRow(rowIndex++); row.CreateCell(0).SetCellValue(asset.AssetCode); row.CreateCell(1).SetCellValue(asset.Name); row.CreateCell(2).SetCellValue(asset.Category?.Name ?? ""); row.CreateCell(3).SetCellValue(asset.CurrentEmployee?.Name ?? "未使用"); row.CreateCell(4).SetCellValue(asset.Location); row.CreateCell(5).SetCellValue(GetStatusName(asset.Status)); row.CreateCell(6).SetCellValue(asset.BuyDate?.ToString("yyyy-MM-dd") ?? ""); row.CreateCell(7).SetCellValue((double)(asset.OriginalValue ?? 0)); } var ms = new MemoryStream(); workbook.Write(ms); return ms; }

导入盘点结果时,我先用 DataTable 接收解析出的 Excel 数据,然后逐行校验资产编号是否存在、盘点状态是否合法、盘点人是否填写,最后整体校验完再入库。这里有个坑:Excel 里如果资产编号列存在格式问题,比如 Excel 把长编号当数值处理导致精度丢失,读出来就成了科学计数法。解决办法是导入模板里把资产编号列格式设置为文本,代码里读单元格时用 DataFormatter 而不是直接拿数值。

3.3 资产二维码标签生成与扫码应用

我对每个资产生成一个唯一的二维码,内容是一个短网址格式,比如 http://asset.local/detail/10001,扫码后直接跳到资产详情页。这样现场盘点时只需要用手机扫一下,就能看到这台设备的全部信息和历史维修记录。

用 ZXing.Net 生成二维码的代码很简洁:

public byte[] GenerateQrCode(int assetId) { var asset = _db.Assets.Find(assetId); string content = $"{Request.Url.Scheme}://{Request.Url.Authority}/Asset/Detail/{asset.Id}"; var writer = new BarcodeWriterPixelData { Format = BarcodeFormat.QR_CODE, Options = new QrCodeEncodingOptions { Height = 200, Width = 200, Margin = 1 } }; var pixelData = writer.Write(content); using (var bitmap = new Bitmap(pixelData.Width, pixelData.Height, PixelFormat.Format32bppRgb)) { var bmpData = bitmap.LockBits(new Rectangle(0, 0, pixelData.Width, pixelData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); Marshal.Copy(pixelData.Pixels, 0, bmpData.Scan0, pixelData.Pixels.Length); bitmap.UnlockBits(bmpData); using (var ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Png); return ms.ToArray(); } } }

二维码打印出来后用亚克力标签牌或防水贴纸贴在设备上,盘点效率会大幅提升。购买固定资产标签纸建议选带背胶的哑面材质,反光材质会导致扫码失败率偏高。

4. 实操过程与部署上线

4.1 从零搭建项目的完整步骤

我用的开发环境是 Visual Studio 2022 + SQL Server 2019 + .NET Framework 4.8(也可以直接上 .NET 6/8,对企业内网部署差异不大)。创建项目的完整过程:

  1. 新建项目,选择“ASP.NET Web 应用程序(.NET Framework)”,模板选“MVC”。
  2. 用 NuGet 安装 EntityFramework、NPOI、ZXing.Net 三个包。
  3. 创建实体类,对应数据库表结构;创建 DbContext 并配置连接字符串。
  4. 启用 Code First 迁移:在程序包管理器控制台执行 Enable-Migrations、Add-Migration Init、Update-Database。
  5. 搭建 Layout 布局页,左侧菜单放资产台账、资产入库、资产领用、资产归还、维修记录、盘点管理、系统管理。
  6. 一个模块一个模块地实现 Controller 和 View,先做基础增删改查,再做业务状态流转。
  7. 用种子数据方法在项目启动时初始化管理员账号和基础分类数据。

比较容易被新手忽略的是连接字符串的配置。我推荐把连接字符串放在 Web.config 里专门为发布准备的配置节,而不是直接写死在本机 ConnectionStrings 里,发布时改一下部署服务器的地址就行。

4.2 部署到 IIS 的避坑要点

部署到 IIS 时可以按下面的步骤来:

  1. 项目右键发布,选择“文件系统”,目标路径设为服务器上的一个文件夹,比如 D:\AssetSys。
  2. IIS 添加网站,物理路径指向发布文件夹,绑定端口建议用 8080 之类不冲突的端口,避免和 80 端口上的其他站点冲突。
  3. 应用程序池选择“集成模式”,.NET CLR 版本选择 v4.0。
  4. 给数据库服务器开启 TCP/IP 协议,确保应用服务器能远程连上。

我实际部署时踩过两个比较隐蔽的坑。第一个是发布时视图文件(.cshtml)没有被一起复制过去,导致运行时提示找不到视图,解决方法是发布配置里把“预编译”选项关闭,或者明确设置包含视图文件。第二个是 IIS 默认请求限制,如果资产图片上传体积超过默认大小会直接报 404.13,需要在 Web.config 里调整 maxAllowedContentLength。

4.3 初始化数据与验收验证

系统上线前一定要做好基础数据的初始化,这一步如果偷懒,后面所有流程都跑不顺。需要准备的基础数据有:部门清单、员工花名册(Excel 导入)、资产分类表、系统用户账号,还有最重要的“初始库存资产”,也就是公司现有的台账资产要批量导入系统作为期初数据。

验收时我建议重点测试这五个场景:

  • 新资产入库后状态是否为“在库”,资产编号是否按规则自动生成
  • 领用操作后,资产状态是否变为“在用”,流水表是否新增记录
  • 同一资产被两个账号同时领用时,系统是否会拒绝其中一个请求
  • 盘点导入后,差异报表能否正确识别出“账有实无”和“实有账无”两类差异
  • 普通员工登录后,是否无法访问资产入库、报废审批等管理页面

5. 常见问题与排查技巧实录

5.1 高频问题排查速查表

我把开发过程中遇到的高频问题整理成了一个速查表,按症状、原因、解决办法三列列出:

问题现象根本原因解决办法
发布后浏览器访问页面报 500 错误Web.config 中的连接字符串指向本机数据库,未改成服务器地址检查并修改连接字符串,确认 SQL Server 允许远程连接
点击“导出 Excel”后下载的文件打不开NPOI 生成的流未调用 Flush 或未设置正确的 Content-Disposition 头返回 File 方法时设置 fileDownloadName 后缀为 .xlsx
二维码扫出来是乱码生成二维码时文本包含中文,而编码格式未指定 UTF-8在写入二维码内容前使用 Encoding.UTF8.GetBytes 转换
盘点导入时提示“资产编号不存在”但 Excel 里明明有Excel 资产编号列被当数值处理,长编号末尾变成 0导入模板设列格式为文本,读取时使用 DataFormatter
用 IE 浏览器打开页面样式全部错乱LayUI 对旧版 IE 兼容性差设定系统只在 Chrome/Edge 下使用,或在页面加浏览器检测提示

5.2 性能优化与并发处理心得

固定资产管理系统虽然不大,数据量上来后还是要注意查询效率。我遇到过的问题是在资产列表页做了多表 Join 后,接口响应时间从 300 毫秒涨到 3 秒,原因是 EF 的延迟加载导致 N+1 查询,每加载一条资产就要额外查一次分类和使用人。后来改成用 Include 方法预加载关联实体,并配合 Select 投影只取需要的列,接口时间直接降回 400 毫秒以内。

并发控制是企业系统的必修课。我在这里要分享一个真实教训:初期领用操作没有做状态校验,结果财务和行政同时在系统里操作,把同一台投影仪领用给了两个不同的部门。后来我在 Service 层加上了对资产状态的检查,并且把资产当前状态作为一个条件放进 Update 语句里,这样即使两个请求同时到达,数据库层面也只允许一个更新成功,另一个更新受影响行数为 0 则自动回滚并提示失败。

5.3 安全性加固与日志留痕

企业资产数据属于敏感信息,安全等级不能太低。我在登录模块做了登录失败次数限制,连续输错 5 次密码锁定账号 30 分钟,防止暴力破解。在查询资产列表的 Action 里统一校验当前用户是否有权查看指定部门的数据,防止越权访问。SQL 注入方面,EF 的参数化查询已经天然规避了大部分风险,但如果是拼接 SQL 的查询方法,必须改用 SqlParameter 传参。

操作留痕是资产管理系统的监管要求,我在所有写操作(添加入库、领用、报废、盘点修改)里都插入了审计记录,内容包括操作时间、操作人、操作类型、变更前后值。这样出了问题可以直接定位到具体操作人和操作内容,不会出现“明明没人动过但数据变了”的扯皮情况。

6. 复盘与后续扩展思路

6.1 系统上线一段时间后的运行体会

这套系统上线后,最直观的效果是资产盘点时间从以前的两周缩短到了两天,资产状态不再靠问、靠猜,打开系统一查就有答案。之前财务最头疼的折旧计算也方便了不少,给资产配上残值率和折旧年限后,系统每月自动生成折旧明细,财务直接导出入账。

我印象最深的一件事是财务部门在月度结账前急需一份全公司资产折旧表,以前得让行政从 Excel 里整理大半天,现在直接在系统里选好月份点导出,两分钟就拿到了。这种隐性效率提升,其实比功能本身更有价值。

6.2 还可以继续完善的功能方向

目前这个版本是一个标准的“记录型”资产管理系统,往后扩展可以考虑几个方向:

一是对接企业微信或钉钉,实现移动端扫码盘点,让现场盘点不再依赖电脑;二是加入资产借用审批流,员工提交申请后由主管在线审批;三是关联财务系统,资产入账、折旧、处置直接生成凭证,减少财务重复录入工作量;四是引入低代码平台做报表自定义,让业务部门自己拉取想要的分析维度,而不是每次都找开发改报表页面。

如果你准备自己动手做一套,我建议从最小可行版本开始:先搞定资产台账的增删改查和领用、归还两条核心流程,跑通之后再逐步加盘点、维修、折旧、报表。一上来就想把所有功能都做全,很容易陷入过度设计,导致项目周期拉长、动力耗尽。

提示:如果你是第一次用 C# 做 Web 项目,建议先把 MVC 的请求管道、EF 的增删改查、前端表单的提交与校验这三件事搞熟,再开始写业务逻辑。这三件事掌握了,剩下的就是业务规则翻译成代码的过程。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询