.Net框架,除了EF还有很多很多......
文章目录
- 1. 引言
- 2. Dapper
- 2.1 概述与设计原理
- 2.2 核心功能与代码示例
- 基本查询
- 多映射查询
- 存储过程调用
- 2.3 性能优化原理
- 2.4 适用场景
- 3. NHibernate
- 3.1 概述与架构设计
- 3.2 映射配置示例
- Fluent映射
- XML映射
- 3.3 查询示例
- HQL查询
- Criteria API
- LINQ提供程序
- 3.4 高级特性
- 3.5 适用场景
- 4. ServiceStack.OrmLite
- 4.1 设计理念
- 4.2 基本操作示例
- 配置与连接
- CRUD操作
- 高级查询
- 4.3 特性与扩展
- 4.4 适用场景
- 5. LLBLGen Pro
- 5.1 框架概述
- 5.2 设计器与代码生成
- 5.3 查询示例
- Adapter模式
- LINQ查询
- 5.4 性能优化技术
- 5.5 适用场景
- 6. PetaPoco
- 6.1 微型ORM设计
- 6.2 基本用法
- 6.3 高级特性
- 6.4 适用场景
- 7. RepoDB
- 7.1 混合ORM设计
- 7.2 核心操作
- 基本CRUD
- 批量操作
- 7.3 性能特性
- 7.4 适用场景
- 8. 框架比较与选型指南
- 8.1 功能对比表
- 8.2 性能基准
- 8.3 选型建议
- 9. 高级主题与最佳实践
- 9.1 混合使用多个ORM
- 9.2 性能优化技巧
- 9.3 事务管理
- Dapper事务
- NHibernate事务
- 9.4 迁移策略
- 10. 结论
1. 引言
Entity Framework (EF)是微软官方推出的.NET ORM框架,但.NET生态系统中还存在许多其他优秀的数据访问框架。本文将全面介绍EF的主要替代方案,包括Dapper、NHibernate、ServiceStack.OrmLite、LLBLGen Pro、PetaPoco等,深入分析它们的原理、架构设计、使用场景,并通过大量代码示例展示它们的实际应用。
2. Dapper
2.1 概述与设计原理
Dapper是由Stack Overflow团队开发的微型ORM框架,其核心设计理念是"轻量级"和"高性能"。与EF不同,Dapper不提供变更跟踪、延迟加载等复杂功能,而是专注于将SQL查询结果快速映射到对象。
Dapper的核心原理:
- 基于ADO.NET的扩展方法
- 动态生成IL代码实现高性能映射
- 无状态设计,不维护对象状态
- 直接使用SQL,不提供查询翻译层
2.2 核心功能与代码示例
基本查询
using var connection = new SqlConnection(connectionString);
var products = connection.Query<Product>("SELECT * FROM Products WHERE Price > @Price", new { Price = 50 });
多映射查询
var sql = @"SELECT * FROM Orders o INNER JOIN Customers c ON o.CustomerId = c.IdWHERE o.OrderDate > @Date";var orders = connection.Query<Order, Customer, Order>(sql,(order, customer) => { order.Customer = customer; return order; },new { Date = DateTime.Now.AddDays(-30) },splitOn: "Id");
存储过程调用
var parameters = new DynamicParameters();
parameters.Add("@ProductId", 1);
parameters.Add("@Price", dbType: DbType.Decimal, direction: ParameterDirection.Output);connection.Execute("sp_GetProductPrice", parameters, commandType: CommandType.StoredProcedure);var price = parameters.Get<decimal>("@Price");
2.3 性能优化原理
Dapper的性能优势主要来自:
- 动态编译:首次查询时会为特定类型生成优化的映射代码
- 缓存机制:生成的映射代码会被缓存,避免重复编译
- 最小化抽象:几乎不添加额外抽象层,直接操作ADO.NET
2.4 适用场景
- 需要极致性能的应用程序
- 已有良好SQL基础,希望直接控制SQL
- 简单CRUD操作为主的系统
- 微服务架构中的轻量级数据访问层
3. NHibernate
3.1 概述与架构设计
NHibernate是.NET平台上的成熟ORM框架,移植自Java的Hibernate。它提供了比EF更丰富的功能集和更灵活的配置选项。
NHibernate架构核心:
- ISession:工作单元模式的实现,管理对象生命周期
- 映射系统:支持XML、特性或Fluent配置
- 查询语言:HQL、Criteria API、LINQ
- 二级缓存:可插拔的缓存实现
3.2 映射配置示例
Fluent映射
public class ProductMap : ClassMap<Product>
{public ProductMap(){Id(x => x.Id);Map(x => x.Name);Map(x => x.Price);References(x => x.Category);HasMany(x => x.OrderItems).Inverse().Cascade.AllDeleteOrphan();}
}
XML映射
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"><class name="Product" table="Products"><id name="Id" column="ProductId"><generator class="identity"/></id><property name="Name" not-null="true"/><property name="Price" type="decimal"/><many-to-one name="Category" column="CategoryId"/><bag name="OrderItems" inverse="true" cascade="all-delete-orphan"><key column="ProductId"/><one-to-many class="OrderItem"/></bag></class>
</hibernate-mapping>
3.3 查询示例
HQL查询
var query = session.CreateQuery("FROM Product p WHERE p.Price > :price").SetDecimal("price", 100m);
var products = query.List<Product>();
Criteria API
var products = session.CreateCriteria<Product>().Add(Restrictions.Gt("Price", 100m)).AddOrder(Order.Asc("Name")).SetMaxResults(10).List<Product>();
LINQ提供程序
var products = session.Query<Product>().Where(p => p.Price > 100m).OrderBy(p => p.Name).Take(10).ToList();
3.4 高级特性
- 二级缓存:配置EhCache等实现
- 拦截器:实现IInterceptor自定义操作行为
- 事件系统:监听和处理持久化事件
- 批量处理:优化大批量数据操作
3.5 适用场景
- 复杂领域模型的企业应用
- 需要跨数据库平台的应用
- 已有Hibernate经验的团队
- 需要细粒度控制持久化行为的场景
4. ServiceStack.OrmLite
4.1 设计理念
ServiceStack.OrmLite是ServiceStack套件中的轻量级ORM,设计目标是提供简单、直观的API,同时保持高性能。它采用"约定优于配置"的原则,自动推断大部分映射关系。
核心特点:
- 基于POCO的无配置映射
- 支持多种数据库提供程序
- 简洁的LINQ-like API
- 与ServiceStack其他组件无缝集成
4.2 基本操作示例
配置与连接
var dbFactory = new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider);using var db = dbFactory.Open();
db.CreateTableIfNotExists<Product>();
CRUD操作
// 插入
var product = new Product { Name = "iPad", Price = 499 };
db.Insert(product);
var id = product.Id; // 自动获取自增ID// 查询
var expensiveProducts = db.Select<Product>(p => p.Price > 1000);// 更新
product.Price = 449;
db.Update(product);// 删除
db.Delete<Product>(p => p.Price < 100);
高级查询
var results = db.Select<Product>(q => q.Where(p => p.Price > 100).OrderBy(p => p.Name).Limit(10, 5)); // 分页
4.3 特性与扩展
- 模式迁移:通过
Migrate()
方法处理数据库变更 - 复杂类型支持:JSON/XML序列化存储复杂属性
- 存储过程支持:通过
SqlProc
方法调用 - 多数据库支持:同一代码可运行在不同数据库上
4.4 适用场景
- 使用ServiceStack构建的Web服务
- 需要简单快速开发的应用程序
- 偏好简洁API的项目
- 需要支持多种数据库的项目
5. LLBLGen Pro
5.1 框架概述
LLBLGen Pro是商业ORM框架,以其强大的设计器和高效运行时著称。它提供三种工作模式:
- Adapter模式:类似传统ADO.NET的工作方式
- SelfServicing模式:类似EF的主动记录模式
- Entity Framework集成:作为EF提供程序
5.2 设计器与代码生成
LLBLGen Pro的核心是其可视化设计器,可以:
- 逆向工程现有数据库
- 设计实体关系模型
- 生成高度优化的数据访问代码
- 自定义模板控制生成结果
5.3 查询示例
Adapter模式
var adapter = new DataAccessAdapter();
var products = new EntityCollection<ProductEntity>();
var filter = (ProductFields.Price > 100m) & ProductFields.Name.Contains("Pro");
adapter.FetchEntityCollection(products, filter);
LINQ查询
var metaData = new LinqMetaData(adapter);
var query = from p in metaData.Productwhere p.Price > 100morderby p.Nameselect p;
var results = query.ToList();
5.4 性能优化技术
LLBLGen Pro采用多种优化技术:
- 预编译查询计划
- 智能批处理
- 高效的变更跟踪
- 可配置的获取策略
5.5 适用场景
- 大型企业应用程序
- 已有复杂数据库结构的项目
- 需要可视化设计工具支持的团队
- 对性能有极高要求的场景
6. PetaPoco
6.1 微型ORM设计
PetaPoco是极简风格的ORM,核心只有一个C#文件。它提供自动POCO映射和基本的CRUD操作,同时支持原始SQL查询。
设计特点:
- 超轻量级(单个.cs文件)
- 自动POCO映射
- 智能参数绑定
- 简单分页支持
6.2 基本用法
var db = new Database("connectionString");// 查询单个对象
var product = db.SingleOrDefault<Product>("SELECT * FROM Products WHERE Id=@0", 1);// 查询列表
var products = db.Query<Product>("SELECT * FROM Products WHERE Price>@0", 50);// 插入
var newProduct = new Product { Name = "New Product", Price = 99.99m };
db.Insert(newProduct);// 分页
var page = db.Page<Product>(2, 10, "SELECT * FROM Products ORDER BY Name");
6.3 高级特性
- T4模板支持:生成强类型POCO
- 多结果集查询:处理存储过程的多个结果集
- 事务支持:简单的事务API
- 异步操作:全面的异步方法支持
6.4 适用场景
- 小型到中型项目
- 需要简单ORM功能的应用程序
- 资源受限的环境
- 快速原型开发
7. RepoDB
7.1 混合ORM设计
RepoDB是Dapper的替代品,结合了微型ORM和完整ORM的特性。它提供:
- 基于ADO.NET的原始性能
- 丰富的CRUD操作
- 批量操作和缓存支持
- 可扩展的映射系统
7.2 核心操作
基本CRUD
// 插入
var product = new Product { Name = "RepoDemo", Price = 49.99m };
var id = connection.Insert<Product, int>(product);// 查询
var result = connection.Query<Product>(p => p.Price > 10m).ToList();// 更新
product.Price = 59.99m;
connection.Update(product);// 删除
connection.Delete<Product>(p => p.Name == "RepoDemo");
批量操作
var products = new List<Product>();
// 填充products...
connection.InsertAll(products);
7.3 性能特性
- 批处理:合并多个操作到单个调用
- 缓存:内置查询结果缓存
- 预编译:动态编译和缓存表达式树
- 混合模式:混合使用原始SQL和LINQ
7.4 适用场景
- 需要比Dapper更多功能但仍需高性能的项目
- 大量批处理操作的应用程序
- 需要灵活查询方式的场景
8. 框架比较与选型指南
8.1 功能对比表
特性 | EF Core | Dapper | NHibernate | OrmLite | LLBLGen Pro | PetaPoco | RepoDB |
---|---|---|---|---|---|---|---|
变更跟踪 | ✓ | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ |
LINQ支持 | ✓ | ✗ | ✓ | 有限 | ✓ | ✗ | 有限 |
延迟加载 | ✓ | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ |
原始SQL | 有限 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
二级缓存 | 扩展 | ✗ | ✓ | ✗ | ✓ | ✗ | ✓ |
迁移工具 | ✓ | ✗ | 扩展 | 有限 | ✓ | ✗ | ✗ |
性能 | 中等 | 高 | 中等 | 高 | 高 | 高 | 高 |
学习曲线 | 中等 | 低 | 高 | 低 | 高 | 低 | 中等 |
8.2 性能基准
以下是各框架在常见操作上的相对性能比较(数值越小越好):
操作 | EF Core | Dapper | NHibernate | OrmLite | LLBLGen Pro | PetaPoco | RepoDB |
---|---|---|---|---|---|---|---|
单对象查询 | 1.2x | 1.0x | 1.5x | 1.1x | 1.1x | 1.0x | 1.0x |
多对象查询(20) | 1.3x | 1.0x | 1.6x | 1.2x | 1.2x | 1.1x | 1.1x |
插入单对象 | 1.4x | 1.0x | 1.8x | 1.1x | 1.2x | 1.0x | 1.0x |
批量插入(1000) | 2.0x | 1.2x | 2.2x | 1.3x | 1.1x | 1.2x | 1.0x |
复杂查询 | 1.5x | 1.0x | 1.7x | 1.4x | 1.3x | 1.1x | 1.1x |
8.3 选型建议
-
企业级复杂应用:
- 首选:NHibernate或LLBLGen Pro
- 理由:功能全面,支持复杂领域模型,有良好的工具支持
-
高性能Web应用:
- 首选:Dapper或RepoDB
- 理由:接近原生ADO.NET的性能,适合大量简单查询
-
快速开发中小型项目:
- 首选:ServiceStack.OrmLite或PetaPoco
- 理由:简单易用,开发效率高
-
微服务架构:
- 首选:Dapper或EF Core
- 理由:Dapper适合简单服务,EF Core适合需要迁移和复杂查询的服务
-
已有复杂数据库的项目:
- 首选:LLBLGen Pro或NHibernate
- 理由:强大的逆向工程和复杂查询支持
9. 高级主题与最佳实践
9.1 混合使用多个ORM
在实际项目中,可以混合使用多个ORM框架以发挥各自优势。例如:
// 使用Dapper处理大量简单查询
public IEnumerable<Product> GetFeaturedProducts()
{using var conn = new SqlConnection(_config.GetConnectionString("Default"));return conn.Query<Product>("SELECT TOP 10 * FROM Products WHERE IsFeatured=1");
}// 使用EF Core处理复杂领域逻辑
public void UpdateProductInventory(int productId, int adjustment)
{using var context = new AppDbContext();var product = context.Products.Include(p => p.Inventory).FirstOrDefault(p => p.Id == productId);product.Inventory.Stock += adjustment;product.Inventory.LastUpdated = DateTime.UtcNow;context.SaveChanges();
}
9.2 性能优化技巧
-
Dapper优化:
- 使用
Buffered=false
处理大量数据 - 预编译参数化查询
- 合理使用多映射
- 使用
-
NHibernate优化:
- 配置适当的抓取策略
- 使用二级缓存
- 批处理写操作
-
通用优化:
- 限制查询字段(避免SELECT *)
- 合理使用分页
- 异步操作
9.3 事务管理
各框架的事务处理示例:
Dapper事务
using var connection = new SqlConnection(connectionString);
connection.Open();using var transaction = connection.BeginTransaction();
try
{connection.Execute("INSERT INTO Orders...", parameters, transaction);connection.Execute("UPDATE Inventory...", parameters, transaction);transaction.Commit();
}
catch
{transaction.Rollback();throw;
}
NHibernate事务
using var session = sessionFactory.OpenSession();
using var transaction = session.BeginTransaction();
try
{session.Save(order);session.Update(inventory);transaction.Commit();
}
catch
{transaction.Rollback();throw;
}
9.4 迁移策略
从EF迁移到其他ORM的注意事项:
- 数据模型调整:可能需要修改实体类以符合目标ORM约定
- 查询重写:LINQ查询可能需要转换为SQL或其他查询语法
- 事务处理:理解不同ORM的事务边界
- 性能测试:迁移后进行全面性能测试
10. 结论
.NET生态系统提供了丰富的ORM选择,从全功能的NHibernate到超轻量级的PetaPoco,各有其适用场景。选择ORM时应考虑:
- 项目复杂度:简单项目适合微型ORM,复杂领域模型需要全功能ORM
- 团队技能:考虑团队对不同ORM的熟悉程度
- 性能需求:高性能需求可能倾向Dapper等轻量方案
- 长期维护:评估框架的活跃度和社区支持
无论选择哪个框架,理解其底层原理和正确使用模式都是实现高效数据访问的关键。建议从简单需求开始,随着项目复杂度增加逐步评估是否需要更强大的ORM功能。