详情

首页手游攻略 浅析如何优雅封装.NET数据库访问层实用指南

浅析如何优雅封装.NET数据库访问层实用指南

佚名 2026-08-27 12:00:02

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“浅析如何优雅封装.NET数据库访问层”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。

理解这一步时,但很多开发者在实际项目中仍然会遇到一个问题: 参数化写法太繁琐,代码臃肿,开发效率低

那么有没有一种方式能够做到:

  • 写法简洁(接近拼接SQL)
  • 自动参数化(安全)
  • 统一规范(易维护)
  • 兼容扩展(日志、事务、重试)

答案是:封装数据库访问层

一、为什么必须封装

先说结论:

不封装数据库访问层,项目后期一定会乱

常用问题:

1. SQL散落各处

// A类
var sql = "SELECT * FROM A WHERE id=@id";

// B类
var sql = "SELECT * FROM A WHERE id=" + id;

写法不统一,维护困难

2. 参数化风格混乱

cmd.Parameters.AddWithValue("@id", id);

每个人写法都不一样

3. 无法统一扩展

比如你想加:

  • SQL日志
  • 执行耗时
  • 重试机制
  • 事务控制

需全项目改代码

所以核心目标:把所有数据库操作收口到一层

二、设计目标(重点)

我们要实现一个工具层,满足:

目标说明
简洁类似拼接SQL写法
安全自动参数化
通用兼容查询/增删改
可扩展日志/事务/重试
易维护统一入口

三、建议方案:类Dapper风格封装

我们实现一个方法:

Execute(sql, new { id = 1, name = "张三" });

看起来像拼接,但其实是参数化

四、核心实现(通用工具类)

1. 执行SQL(增删改)

public static int Execute(string sql, object param = null)
{
    using (var conn = new SqlConnection(connStr))
    {
        using (var cmd = new SqlCommand(sql, conn))
        {
            if (param != null)
            {
                AddParameters(cmd, param);
            }

            conn.Open();
            return cmd.ExecuteNonQuery();
        }
    }
}

2. 查询单条

public static T QueryFirst<T>(string sql, object param = null) where T : new()
{
    using (var conn = new SqlConnection(connStr))
    using (var cmd = new SqlCommand(sql, conn))
    {
        if (param != null)
        {
            AddParameters(cmd, param);
        }

        conn.Open();
        using (var reader = cmd.ExecuteReader())
        {
            if (!reader.Read()) return default;

            var obj = new T();
            foreach (var prop in typeof(T).GetProperties())
            {
                if (!reader.HasColumn(prop.Name)) continue;

                var val = reader[prop.Name];
                if (val != DBNull.Value)
                    prop.SetValue(obj, val);
            }

            return obj;
        }
    }
}

3. 参数自动映射(核心)

private static void AddParameters(SqlCommand cmd, object param)
{
    foreach (var prop in param.GetType().GetProperties())
    {
        var value = prop.GetValue(param) ?? DBNull.Value;
        cmd.Parameters.AddWithValue("@" + prop.Name, value);
    }
}

这一步就是关键:把匿名对象 → 自动转成SQL参数

五、采用方式(对比)

旧写法(拼接)

var sql = $"SELECT * FROM User WHERE Name='{name}'";

新写法(建议)

var sql = "SELECT * FROM User WHERE Name=@Name";
var user = QueryFirst<User>(sql, new { Name = name });

优点:

  • 简洁
  • 安全
  • 可读性强

六、进阶优化(项目实战重点)

1. SQL日志(强烈建议)

Stopwatch sw = Stopwatch.StartNew();

var result = cmd.ExecuteNonQuery();

sw.Stop();
Console.WriteLine($"SQL执行耗时:{sw.ElapsedMilliseconds}ms");
Console.WriteLine(sql);

在MES/WMS中很重要(排查慢SQL)

2. 异常重试机制

适用来:

  • 数据库瞬时连接失败
  • 网络抖动
int retry = 3;
while (retry-- > 0)
{
    try
    {
        return cmd.ExecuteNonQuery();
    }
    catch
    {
        if (retry == 0) throw;
        Thread.Sleep(200);
    }
}

3. 事务封装

public static void ExecuteInTransaction(Action<SqlConnection, SqlTransaction> action)
{
    using var conn = new SqlConnection(connStr);
    conn.Open();

    using var tran = conn.BeginTransaction();

    try
    {
        action(conn, tran);
        tran.Commit();
    }
    catch
    {
        tran.Rollback();
        throw;
    }
}

用法:

ExecuteInTransaction((conn, tran) =>
{
    Execute("INSERT ...", param1, conn, tran);
    Execute("UPDATE ...", param2, conn, tran);
});

4. 防止动态SQL注入(白名单)

var allowedColumns = new[] { "Name", "Age" };

if (!allowedColumns.Contains(column))
{
    throw new Exception("非法字段");
}

七、适配你当前技术栈(重点)

你现在用:

  • .NET
  • PostgreSQL / SQL Server
  • MES / WMS
  • 高并发 + 设备数据

建议:

1. PostgreSQL(Npgsql)

把:

SqlCommand

换成:

NpgsqlCommand

2. 高频接口建议

必须加:

  • SQL日志
  • 超时控制
  • 重试机制

3. 设备数据(你做过Socket)

强烈建议:

  • 所有入库操作必须参数化
  • 禁止拼接

八、什么时候不用自己封装

直接说实话:

如果项目不复杂,直接用:

  • Dapper(强烈建议)
  • SqlSugar(你已经在用)
  • FreeSQL

你自己封装适合:

  • 公司没有规范
  • 项目需统一风格
  • 想做技术沉淀

九、总结

数据库访问层的本质:不是为了封装而封装,而是为了统一和可控

到此这篇关于浅析如何优雅封装.NET数据库访问层的文章就介绍到这了,更多相关.NET封装数据库访问层内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!

您可能感兴趣的文章:
  • .NET4.7采用NLog记录日志到数据库表
  • .NET采用C#导入Excel文件数据到数据库
  • 如何采用.NET8 新建采用MySQL数据库的webapi项目
  • 实现.Net7下数据库定时检查的方法详解
  • ASP.NET MVC把数据库中枚举项的数字转换成文字
  • .Net ORM 访问 Firebird 数据库的方法
  • Asp.net core借助dynamic简化数据库访问
点击查看更多
推荐专题
热门阅读