电影
informix函数(LinqToDB 从入门到精通:示例驱动教程)

简介

  • LinqToDB 是一个轻量、高性能的 ORM/微型 DAL,核心特点是对 SQL 的最小封装,保留 LINQ 的表达式能力,同时最大化控制底层 SQL,减少运行时开销。
  • Dapper、FreeSql 等对比:
    • Dapper:低级别映射,SQL 全手写;
    • FreeSql:功能丰富,自动结构同步;
    • LinqToDBLINQ→SQL 转换最优、支持静态编译查询、拥有强大的 BulkCopy、跨数据库迁移脚本等工具。

LinqToDB 的设计理念

  • 类型安全:使用 LINQ 表达式,避免字符串拼接的 SQL 查询,编译器可检查查询语法。
  • 高性能:接近 Dapper 的性能,优于 Entity framework Core,减少不必要的开销。
  • 轻量级:无复杂的功能(如变更跟踪),提供薄的抽象层,开发者可直接控制 SQL
  • 灵活性:支持 LINQ、原始 SQL、批量操作、事务和数据库特定功能。

LinqToDB 的核心特性

类型安全的 LINQ 查询:

  • 使用 LINQ 表达式查询数据库,编译器可验证查询语法,减少运行时错误。
  • 支持复杂的查询(如联接、分组、子查询)。

多数据库支持:

  • 支持主流数据库:SQL Server、MySQL、PostgreSQL、SQLite、Oracle、Access、Firebird、Informix、DB2 等。
  • 提供数据库特定的扩展(如 SQL Server 的 MERGE、PostgreSQL 的 FOR UPDATe)。

高性能:

  • 接近 ADO.NETDapper 的性能,优于 Entity framework Core
  • 支持批量插入(Bulk Copy)、异步查询和高效的对象映射。

灵活的映射:

  • 支持特性映射(如 [Table]、[Column])和 Fluent 映射。
  • 支持动态表名、跨数据库查询和自定义映射。

无变更跟踪:

  • 不像 Entity framework Core,LinqToDB 不跟踪对象状态,开发者需手动管理更新。
  • 优点是更低的开销和更高的控制权。

扩展性:

  • 支持自定义 SQL 提示(Hints)、拦截器和数据库特定功能。
  • 集成 ASP.NET Core 依赖注入和 Entity framework Core

其他功能:

  • 支持事务、窗口函数(Window Functions)、MERGE 语句。
  • 提供 CLI 工具和 T4 模板用于数据库模型生成。

安装与基础配置

安装 NuGet 包

dotnet add package linq2dbdotnet add package linq2db.SqlServer    # 或 MySql/PostgreSQL/Oracle 等具体 Provider

连接字符串与上下文

// 继承 DataConnection,或直接使用 DataConnectionpublic class AppDb : LinqToDB.Data.DataConnection{    public AppDb() : base("MyConnectionStringName") { }    public ITable<User> Users => GetTable<User>();    public ITable<Order> Orders => GetTable<Order>();}

"MyConnectionStringName" 对应 appsettings.jsonConfigurationManager.ConnectionStrings 中的连接串。

继承 DataContext 类封装连接

public class AppDbContext : DataContext{    public AppDbContext() : base(ProviderName.SQLite, "Data Source=app.db") { }    public ITable<Product> Products => GetTable<Product>();}
  • DataConnection:保持连接直到 Dispose,适合需要长时间保持连接的场景。
  • DataContext:每次查询打开和关闭连接,类似 Entity framework

注册到 DI(.NET Core/.NET 6+)

builder.Services  .AddLinqToDBContext<AppDb>((provider, options) =>      options        .UseConnectionString(ProviderName.SqlServer, configuration.GetConnectionString("Default"))        .UseDefaultLogging(provider.GetService<ILoggerFactory>())  );

核心 CRUD 与 LINQ 查询

查询

using var db = new AppDb();// 简单查询var adults = db.Users    .Where(u => u.Age >= 18)    .OrderBy(u => u.Name)    .ToList();// LINQ 查询var query = from p in db.Products    where p.Price > 15.00m    orderby p.Name descending    select p;var result = query.ToList();// 关联查询var orders = db.Employees    .Where(e => e.EmployeeID == 1)    .SelectMany(e => e.Orders)    .Where(o => o.OrderDate > DateTime.Today.AddYears(-1))    .ToList();// 投影查询var names = db.Users    .Where(u => u.IsActive)    .Select(u => new { u.Id, u.Name })    .ToList();

插入/更新/删除

// 插入单条并返回自增 Idvar newUser = new User { Name = "Alice", Age = 28 };int id = db.InsertWithInt32Identity(newUser);// 插入db.Insert(new Product { Name = "Laptop", Price = 1200 });// 批量插入db.BulkCopy(new BulkCopyOptions(), listOfUsers);// 更新int upd = db.Users    .Where(u => u.Id == id)    .Set(u => u.Age, 30)    .Update();// 删除int del = db.Users    .Where(u => u.Age < 18)    .Delete();

实体映射与模型配置

属性映射

// 方式1:使用特性[Table(Name = "Users")]public class User{    [PrimaryKey, Identity]    public int Id { get; set; }        [Column(Name = "UserName"), NotNull]    public string Name { get; set; }        [Column(IsColumn = false)] // 不映射到数据库    public string FullName => $"{LastName}, {FirstName}";}

Fluent API 配置

// 方式2:使用 Fluent APIpublic class MyMappingSchema : MappingSchema{    public MyMappingSchema() : base("MySchema")    {        var builder = GetFluentMappingBuilder();                builder.Entity<User>()            .HasTableName("Users")            .HasPrimaryKey(u => u.Id)            .Property(u => u.Id).IsIdentity()            .Property(u => u.Name).HasColumnName("UserName");    }}

多库与多模式支持

  • UseConnectionString 中指定不同的 Provider
options.UseConnectionString(ProviderName.PostgreSQL, pgConn)       .UseConnectionString(ProviderName.MySql, myConn);
  • 支持在同一上下文中查询不同数据库,只要映射定义一致。

进阶特性

多数据库连接

通过不同连接字符串名区分多个数据库

using (var db1 = new DataContext("DB1_Config"))using (var db2 = new DataContext("DB2_Config")) {  }

编译查询(Compiled Queries)

对性能要求极高场景,可预编译 LINQ→SQL 转换:

static readonly Func<AppDb, int, List<User>> GetByMinAge =    CompiledQuery.Compile((AppDb db, int minAge) =>        db.Users.Where(u => u.Age >= minAge).ToList());var adults = GetByMinAge(db, 18);
  • 减少表达式树解析开销,适合高并发和热路径。

BulkCopy 与批量操作

  • BulkCopy:对比 InsertWithIdentity,批量插入数万条性能提升数十倍。
  • Merge:基于 SQL ServerMERGE 语法,实现 UPSERT
db.BulkCopy(new BulkCopyOptions { BulkCopyType = BulkCopyType.Merge }, list);

事务处理

using (var db = new MyDataContext())using (var transaction = db.BeginTransaction()){    try    {        // 操作1        db.Insert(new User { Name = "Transaction User", Age = 30 });                // 操作2        db.Users            .Where(u => u.Name == "Old User")            .Set(u => u.Age, u => u.Age + 1)            .Update();                // 提交事务        transaction.Commit();    }    catch (Exception)    {        // 回滚事务        transaction.Rollback();        throw;    }}

批量操作

using (var db = new MyDataContext()){    // 批量插入    var users = new List<User>    {        new User { Name = "User1", Age = 20 },        new User { Name = "User2", Age = 21 },        new User { Name = "User3", Age = 22 }    };        db.BulkCopy(users);        // 批量更新    var usersToUpdate = db.Users        .Where(u => u.Age < 25)        .ToList();        foreach (var user in usersToUpdate)    {        user.Age += 1;    }        db.BulkUpdate(usersToUpdate);}

异步操作

using (var db = new MyDataContext()){    // 异步查询    var users = await db.Users        .Where(u => u.Age > 18)        .ToListAsync();        // 异步插入    var newUser = new User { Name = "Async User", Age = 30 };    await db.InsertAsync(newUser);}

复杂查询支持

  • join 查询
using (var db = new DbNorthwind()){    var query = from p in db.Products                join c in db.Categories on p.CategoryID equals c.CategoryID                select new { ProductName = p.Name, CategoryName = c.Name };    var result = query.ToList();}
  • 子查询:
using (var db = new DbNorthwind()){    var subQuery = db.Products.Where(p => p.Price > 20.00m).Select(p => p.CategoryID);    var query = db.Categories.Where(c => subQuery.Contains(c.CategoryID));    var result = query.ToList();}
  • 分页:
using (var db = new DbNorthwind()){    var query = db.Products.OrderBy(p => p.Name).Skip(10).Take(5);    var result = query.ToList();}
  • 联合查询(Union
var query1 = db.Products.Where(p => p.Price < 10);var query2 = db.Products.Where(p => p.Price > 100);var unionResults = query1.Union(query2).ToList();
  • 关联查询:通过 Association 属性定义导航关系
[Association(ThisKey = "DepartmentID", OtherKey = "DepartmentID")]public Department Department { get; set; }

存储过程调用

[StoredProcedure("CustOrderHist")]public class CustOrderHistResult{    [Column("ProductName")]    public string ProductName { get; set; }        [Column("Total")]    public int Total { get; set; }}using (var db = new NorthwindDataConnection()){    var parameters = new DataParameter[]    {        new DataParameter("@CustomerID", "ALFKI")    };        var results = db.QueryProc<CustOrderHistResult>("CustOrderHist", parameters);}

窗口函数支持

var rankedEmployees = db.Employees    .Select(e => new    {        e.LastName,        e.FirstName,        RowNumber = Sql.Ext.RowNumber()            .Over()            .PartitionBy(e.Title)            .OrderBy(e.HireDate)            .ToValue()    })    .ToList();

SQL 拦截与日志

db.onTrace = new TraceInfo{    BeforeExecute = info => Console.WriteLine(info.SqlText),    AfterExecute  = info => Console.WriteLine($"Count:{info.RecordCount}")};
  • 可在拦截器中修改 SQL、参数,或将日志写入自定义管道。

性能优化与最佳实践

重用 DataConnection

  • 在同一请求/作用域内复用,不要频繁 new
  • 配合 DI 容器管理生命周期。

使用编译查询

  • 热点路径、复杂查询强烈推荐,能显著降低 CPU 开销。

Bulk 操作

  • 对大批量数据,务必使用 BulkCopyMerge,避免逐条插入。

显式投影

  • 不要在 LINQ 中拉取整个实体,尽量 Select 出需要字段,减少网络与内存压力。

控制查询深度

  • 避免不必要的 Join;对大对象图,分步查询或分割 DTO

日志与监控

  • 在开发/测试环境打开 OnTrace,生产环境可降级为 WARN 级别或写文件。

事务粒度

  • 控制在最小范围内使用事务,长事务会锁表、阻塞并发。

避免 N+1 查询:使用 LoadWith 预加载关联数据

var employees = db.Employees    .LoadWith(e => e.Orders)    .ThenLoad(o => o.OrderDetails)    .ToList();

资源与扩展

  • 官方文档:https://linq2db.github.io/
  • GitHub 仓库:https://github.com/linq2db/linq2db
  • 示例项目:https://github.com/linq2db/examples
  • 扩展包
    • linq2db.EntityframeworkCore:在 EF Core 项目中使用 LinqToDB 功能。
    • LinqToDB.IdentityASP.NET Core Identity 提供程序
  • CLI 工具:支持数据库模型生成和 T4 模板定制:https://linq2db.github.io/articles/CLI.html

总结

LinqToDB.NET 生态中一个高性能、轻量级的 ORM 解决方案,特别适合:

  • 需要接近原生数据库性能的应用
  • 处理复杂查询和大数据量的场景
  • 对启动时间和内存占用敏感的环境
  • 需要与多种数据库兼容的项目

核心优势:

  • 极佳的性能表现
  • 简洁轻量的设计
  • 强大的 SQL 生成能力
  • 全面的数据库支持

推荐使用场景:

  • 报表生成系统
  • 数据分析和 ETL 处理
  • 高性能 API 后端
  • 数据库迁移工具

顶一下()     踩一下()

热门推荐

发表评论
0评