1. 为什么需要.NET数据库操作框架
在.NET生态中,数据访问一直是开发中的高频操作。记得我2013年刚接触C#时,还在用ADO.NET手动拼接SQL字符串,一个分页查询就要写十几行样板代码。后来Entity Framework的出现确实带来了变革,但EF的复杂性又让很多简单项目望而却步。这就是为什么我们需要一个"简单但够用"的数据库操作框架。
典型的痛点场景包括:
- 快速原型开发时不想配置复杂的ORM
- 遗留系统改造时需要轻量级数据访问层
- 微服务中仅需基础CRUD功能
- 教学演示场景需要直观的数据操作示例
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 框架设计核心思路
2.1 轻量级架构设计
我们的框架采用经典的三层结构:
code复制[客户端代码]
↓
[框架核心] → [SQL构建器]
↓
[ADO.NET驱动]
与Dapper类似,我们基于ADO.NET封装,但提供了更符合国人习惯的链式API。比如查询条件构建:
csharp复制var users = DB.Queryable<User>()
.Where(u => u.Age > 18)
.OrderBy(u => u.CreateTime)
.ToList();
2.2 关键接口设计
核心接口仅包含5个主要方法:
csharp复制public interface IDatabase
{
IEnumerable<T> Query<T>(string sql, object parameters = null);
int Execute(string sql, object parameters = null);
// 分页查询、事务管理等...
}
这种极简设计使得学习曲线非常平缓,新手也能快速上手。
3. 核心实现技术细节
3.1 高性能参数化查询
防SQL注入是基础要求,我们采用动态参数化处理:
csharp复制public IEnumerable<T> Query<T>(string sql, object parameters)
{
using var cmd = _connection.CreateCommand();
cmd.CommandText = sql;
foreach (var prop in parameters.GetType().GetProperties())
{
var param = cmd.CreateParameter();
param.ParameterName = $"@{prop.Name}";
param.Value = prop.GetValue(parameters);
cmd.Parameters.Add(param);
}
// 执行查询...
}
3.2 智能类型转换器
处理数据库NULL值和类型转换时:
csharp复制private static T ConvertValue<T>(object dbValue)
{
if (dbValue == DBNull.Value)
return default;
if (typeof(T) == typeof(Guid))
return (T)(object)Guid.Parse(dbValue.ToString());
// 其他特殊类型处理...
return (T)Convert.ChangeType(dbValue, typeof(T));
}
4. 高级功能实现
4.1 事务管理
提供两种事务模式:
csharp复制// 显式事务
using (var tx = DB.BeginTransaction())
{
try {
DB.Execute("UPDATE...", ..., tx);
DB.Execute("INSERT...", ..., tx);
tx.Commit();
} catch {
tx.Rollback();
}
}
// 自动事务
DB.Transaction(() => {
DB.Execute("UPDATE...");
DB.Execute("INSERT...");
});
4.2 多数据库支持
通过策略模式实现多数据库适配:
csharp复制public interface IDbAdapter
{
string BuildPaginationSql(string sql, int page, int size);
DbParameter CreateParameter(string name, object value);
}
// SQL Server实现
public class SqlServerAdapter : IDbAdapter
{
public string BuildPaginationSql(string sql, int page, int size)
{
return $@"
WITH TempResult AS ({sql})
SELECT * FROM TempResult
ORDER BY Id
OFFSET {(page-1)*size} ROWS
FETCH NEXT {size} ROWS ONLY";
}
}
5. 性能优化实践
5.1 连接池管理
csharp复制public class DbContext
{
private static ConcurrentDictionary<string, DbConnection> _connections
= new ConcurrentDictionary<string, DbConnection>();
public static DbConnection GetConnection(string connStr)
{
return _connections.GetOrAdd(connStr, s => {
var conn = new SqlConnection(s);
conn.Open();
return conn;
});
}
}
5.2 缓存策略
对于配置表等低频变更数据:
csharp复制public class CachedRepository
{
private static MemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
public IEnumerable<T> QueryWithCache<T>(string cacheKey, Func<IEnumerable<T>> getter)
{
if (_cache.TryGetValue(cacheKey, out IEnumerable<T> data))
return data;
data = getter();
_cache.Set(cacheKey, data, TimeSpan.FromMinutes(30));
return data;
}
}
6. 实战应用案例
6.1 电商订单处理
csharp复制public class OrderService
{
public void CreateOrder(Order order, List<OrderDetail> details)
{
DB.Transaction(() => {
var orderId = DB.ExecuteScalar<int>(
"INSERT INTO Orders(...) VALUES(...); SELECT SCOPE_IDENTITY()",
order);
details.ForEach(d => d.OrderId = orderId);
DB.BulkInsert("OrderDetails", details);
});
}
}
6.2 报表数据导出
csharp复制public DataTable ExportUserReport(DateTime start, DateTime end)
{
return DB.QueryTable(@"
SELECT u.Name, COUNT(o.Id) as OrderCount
FROM Users u
LEFT JOIN Orders o ON u.Id = o.UserId
WHERE u.CreateTime BETWEEN @start AND @end
GROUP BY u.Name",
new { start, end });
}
7. 常见问题解决方案
7.1 连接泄漏检测
csharp复制// 在开发环境启用连接检查
#if DEBUG
AppDomain.CurrentDomain.ProcessExit += (s, e) => {
var leaks = _connections.Count;
if (leaks > 0)
Debug.WriteLine($"警告!检测到{leaks}个未关闭的数据库连接");
};
#endif
7.2 慢查询监控
csharp复制public class DbCommandInterceptor : IDbCommandInterceptor
{
public void ReaderExecuting(DbCommand command)
{
var stopwatch = Stopwatch.StartNew();
command.Tag = stopwatch;
}
public void ReaderExecuted(DbCommand command)
{
var elapsed = ((Stopwatch)command.Tag).ElapsedMilliseconds;
if (elapsed > 500) // 超过500ms记录警告
Logger.Warn($"慢查询检测: {command.CommandText} ({elapsed}ms)");
}
}
8. 框架扩展方向
8.1 支持更多数据库
当前已支持:
- SQL Server
- MySQL
- PostgreSQL
计划支持:
- SQLite
- Oracle
8.2 分布式事务
基于Saga模式实现:
csharp复制public class SagaCoordinator
{
public void Execute(params ISagaOperation[] operations)
{
var compensations = new Stack<Action>();
try {
foreach (var op in operations)
{
op.Execute();
compensations.Push(op.Compensate);
}
} catch {
while (compensations.Count > 0)
compensations.Pop()?.Invoke();
throw;
}
}
}
在.NET生态中构建数据库访问层时,最重要的是把握"适度封装"的原则。经过多个项目的验证,这个框架在保持简单性的同时,通过扩展点设计满足了大部分业务场景需求。对于刚接触.NET的开发者,建议先从基础CRUD操作开始,逐步探索更高级的特性。
