ORMX的连表查询功能 - 开发日志,连表查询, Join, InnerJoin, LeftJoin, RightJoin, FullJoin, 多表连接, DTO映射 - 学习ORMX的连表查询功能,包括INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN等连接类型,以及多表连接和Join上下文的使用方法。

您当前正在浏览的是本站SEO版网页

请点击确认

马上提升浏览体验

ORMX的连表查询功能

编程 数据库 阅读:0
2/8/2026 9:14:41 PM

学习ORMX的连表查询功能,包括INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN等连接类型,以及多表连接和Join上下文的使用方法。 关键字:连表查询, Join, InnerJoin, LeftJoin, RightJoin, FullJoin, 多表连接, DTO映射

第九章:连表查询

9.1 Join 概述

Join 是关系型数据库中最强大的功能之一,它允许您根据两个表之间的关系,将它们的数据组合在一起。ORMX 提供了完整的 Join 支持,包括:

  • 内连接(INNER JOIN):只返回两个表中匹配的行
  • 左连接(LEFT JOIN):返回左表的所有行,以及右表中匹配的行
  • 右连接(RIGHT JOIN):返回右表的所有行,以及左表中匹配的行
  • 全连接(FULL JOIN):返回两个表中的所有行

9.1.1 为什么需要 Join?

在实际应用中,数据通常分布在多个表中:

// 用户表
public class User
{
    [Column(IsPrimaryKey = true, IsAutoIncrement = true)]
    public int Id { get; set; }
    
    public string Name { get; set; }
    public string Email { get; set; }
}

// 订单表
public class Order
{
    [Column(IsPrimaryKey = true, IsAutoIncrement = true)]
    public int Id { get; set; }
    
    public int UserId { get; set; }  // 外键,关联到 User 表
    
    public decimal Amount { get; set; }
    public DateTime OrderDate { get; set; }
}

// 产品表
public class Product
{
    [Column(IsPrimaryKey = true, IsAutoIncrement = true)]
    public int Id { get; set; }
    
    public int OrderId { get; set; }  // 外键,关联到 Order 表
    
    public string ProductName { get; set; }
    public decimal Price { get; set; }
}

使用 Join,您可以轻松地查询这些关联数据:

// 查询用户及其订单
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList();

9.2 Join 最佳实践

在使用 Join 功能时,遵循以下最佳实践可以提高代码质量和可维护性。

9.2.1 使用 DTO 对象

创建专门的 DTO 对象来接收 Join 查询结果:

public class UserOrderDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int? OrderId { get; set; }
    public decimal? OrderAmount { get; set; }
}

优势:

  • 明确的数据结构,避免使用匿名类型
  • 可以在多个地方复用
  • 便于单元测试和维护

9.2.2 使用有意义的别名

在 DTO 中使用有意义的属性名:

public class UserOrderDto
{
    public int UserId { get; set; }        // 用户 ID
    public string UserName { get; set; }      // 用户名
    public int? OrderId { get; set; }        // 订单 ID
    public decimal? OrderAmount { get; set; }  // 订单金额
}

建议:

  • 使用表名作为前缀,如 UserIdUserNameOrderId
  • 避免使用 IdName 等通用名称
  • 添加注释说明字段的含义

9.2.3 DTO 映射机制

ORMX 框架提供灵活的 DTO 映射机制,支持多种映射方式:

9.2.3.1 基本映射(属性名匹配)

DTO 属性名称需与数据库列名称一致:

public class UserOrderSimpleDto
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public int Age { get; set; }
    public string? ProductName { get; set; }
    public decimal? Price { get; set; }
    public int? Quantity { get; set; }
}

9.2.3.2 别名映射(ColumnAttribute)

使用 ColumnAttribute 指定数据库列名:

using JCode.ORMX.Attributes;

public class UserOrderDto
{
    [Column("Name")]
    public string? UserName { get; set; }
    
    [Column("Age")]
    public int? UserAge { get; set; }
    
    [Column("Price")]
    public decimal? OrderPrice { get; set; }
    
    [Column("Quantity")]
    public int? OrderQuantity { get; set; }
}

9.2.3.3 自动前缀映射

ORMX 支持自动表前缀映射,无需显式指定 ColumnAttribute

public class UserOrderAutoDto
{
    // 自动映射规则:
    // UserId -> User.Id 列
    // UserName -> User.Name 列
    // UserAge -> User.Age 列
    // OrderId -> Order.Id 列
    // OrderPrice -> Order.Price 列
    // OrderQuantity -> Order.Quantity 列
    
    public int UserId { get; set; }
    public string? UserName { get; set; }
    public int UserAge { get; set; }
    
    public int OrderId { get; set; }
    public decimal OrderPrice { get; set; }
    public int OrderQuantity { get; set; }
}

映射优先级:

  1. ColumnAttribute 指定的列名(最高优先级)
  2. 直接属性名匹配
  3. 自动前缀映射(如 UserIdUser.IdOrderPriceOrder.Price

自动前缀映射规则:

  • 当属性名以表名开头时,会自动移除表名前缀,映射到对应列
  • 例如:UserId 映射到 User.IdOrderPrice 映射到 Order.Price
  • 注意: 不支持直接的后缀映射(如 NameUserName),仅支持前缀移除

9.2.4 DTO 命名规范

使用统一的命名规范可以提高代码的可读性和可维护性。通常使用以下命名规范:

  • XxxDto:通用的数据传输对象

    • 示例:UserOrderDtoOrderProductDtoUserOrderStats
    • 用途:用于接收查询结果、API 响应等
  • XxxViewModel:用于视图展示的数据对象

    • 示例:UserOrderViewModelOrderListViewModel
    • 用途:用于 UI 展示,可能包含格式化后的数据
  • XxxResponse:用于 API 响应的数据对象

    • 示例:UserOrderResponseCreateOrderResponse
    • 用途:用于 Web API 的响应数据
  • XxxRequest:用于 API 请求的数据对象

    • 示例:CreateOrderRequestUpdateUserRequest
    • 用途:用于 Web API 的请求数据

在 ORMX 中推荐使用 Dto 后缀,如:

// Join 查询结果
public class UserOrderDto { }
public class OrderProductDto { }
public class UserOrderStats { }

// 聚合查询结果
public class UserAgeGroupDto { }
public class DepartmentSalesDto { }

命名建议:

  1. 使用完整的表名UserOrderDto 而不是 UO_Dto
  2. 使用有意义的组合UserOrderDto 表示用户和订单的组合
  3. 保持一致性:整个项目中使用相同的命名规范
  4. 避免缩写UserOrderDto 而不是 UsrOrdDto

9.2.5 DTO 使用示例

9.2.5.1 基本 DTO 使用

// 定义简单 DTO
public class UserOrderSimpleDto
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public int Age { get; set; }
    public string? ProductName { get; set; }
    public decimal? Price { get; set; }
}

// 查询并映射到 DTO
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderSimpleDto>();

9.2.5.2 别名 DTO 使用

// 定义带别名的 DTO
public class UserOrderDto
{
    [Column("Name")]
    public string? UserName { get; set; }
    
    [Column("Age")]
    public int? UserAge { get; set; }
    
    [Column("Price")]
    public decimal? OrderPrice { get; set; }
}

// 查询并映射到 DTO
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

9.2.5.3 自动前缀 DTO 使用

// 定义自动前缀 DTO
public class UserOrderAutoDto
{
    public int UserId { get; set; }
    public string? UserName { get; set; }
    public int UserAge { get; set; }
    
    public int OrderId { get; set; }
    public decimal OrderPrice { get; set; }
    public int OrderQuantity { get; set; }
}

// 查询并映射到 DTO
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderAutoDto>();

9.2.6 使用类型安全的上下文

使用 As<T>() 方法访问连接的表,确保类型安全:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Where(ctx => ctx.As<User>().Age > 25)
    .OrderByDesc(ctx => ctx.As<Order>().OrderDate)
    .GetList<UserOrderDto>();

优势:

  • 编译时类型检查
  • IntelliSense 支持
  • 避免拼写错误

9.3 基本 Join 操作

9.3.1 内连接(INNER JOIN)

内连接只返回两个表中匹配的行。这是最常用的 Join 类型。

using var userTable = tableManager.Table<User>();

// 查询有订单的用户
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

生成的 SQL:

SELECT * FROM User 
INNER JOIN Order ON User."Id" = Order."UserId"

使用场景:

  • 只需要两个表中都存在的数据
  • 例如:查询有订单的用户

9.3.2 左连接(LEFT JOIN)

左连接返回左表(主表)的所有行,以及右表中匹配的行。如果右表中没有匹配的行,则返回 NULL。

// 查询所有用户,包括没有订单的用户
var result = userTable
    .LeftJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

生成的 SQL:

SELECT * FROM User 
LEFT JOIN Order ON User."Id" = Order."UserId"

使用场景:

  • 需要主表的所有数据,即使关联表中没有匹配的数据
  • 例如:查询所有用户,包括没有订单的用户

9.3.3 右连接(RIGHT JOIN)

右连接返回右表的所有行,以及左表中匹配的行。如果左表中没有匹配的行,则返回 NULL。

// 查询所有订单,包括没有关联用户的订单
var result = userTable
    .RightJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

生成的 SQL:

SELECT * FROM User 
RIGHT JOIN Order ON User."Id" = Order."UserId"

使用场景:

  • 需要关联表的所有数据,即使主表中没有匹配的数据
  • 例如:查询所有订单,包括没有关联用户的订单

9.3.4 全连接(FULL JOIN)

全连接返回两个表中的所有行。如果某行在另一个表中没有匹配的行,则返回 NULL。

// 查询所有用户和所有订单
var result = userTable
    .FullJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

生成的 SQL:

SELECT * FROM User 
FULL JOIN Order ON User."Id" = Order."UserId"

使用场景:

  • 需要两个表的所有数据
  • 例如:查询所有用户和所有订单的完整列表

9.4 Join 条件

9.4.1 简单 Join 条件

最简单的 Join 条件是使用相等比较:

// 使用主键和外键关联
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

9.4.2 复杂 Join 条件

您可以使用各种比较运算符和逻辑运算符:

// 使用多个条件
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId && o.Amount > 100)
    .GetList<UserOrderDto>();

// 使用不等运算符
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id != o.UserId)
    .GetList<UserOrderDto>();

// 使用范围条件
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId && o.OrderDate >= DateTime.Now.AddDays(-30))
    .GetList<UserOrderDto>();

9.5 Join 上下文

Join 上下文提供了类型安全的表访问方法。使用 As<T>() 方法,您可以安全地访问已连接的表:

9.5.1 访问连接的表

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Where(ctx => ctx.As<User>().Age > 25 && ctx.As<Order>().Amount > 100)
    .GetList<UserOrderDto>();

9.5.2 在聚合函数中使用

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GroupBy(ctx => ctx.As<User>().Id)
    .Max(ctx => ctx.As<Order>().Amount, "MaxAmount")
    .Count(ctx => ctx.As<Order>().Id, "OrderCount")
    .GetList<UserOrderStats>();

关于聚合函数的详细用法,请查阅聚合函数

9.5.3 在排序中使用

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .OrderByDesc(ctx => ctx.As<Order>().OrderDate)
    .GetList<UserOrderDto>();

9.6 Join 专用查询方法

Join 后,您可以使用专用的查询方法来访问连接的表:

9.6.1 Join Where 方法

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Where(ctx => ctx.As<User>().Age > 25)
    .Where(ctx => ctx.As<Order>().Amount > 100)
    .GetList<UserOrderDto>();

9.6.2 Join Between 方法

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Between(ctx => ctx.As<Order>().Amount, 100, 1000)
    .GetList<UserOrderDto>();

9.6.3 Join In 方法

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .In(ctx => ctx.As<Order>().Status, 1, 2, 3)
    .GetList<UserOrderDto>();

9.6.4 Join Like 方法

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Like(ctx => ctx.As<User>().Name, "张%")
    .GetList<UserOrderDto>();

9.6.5 Join WhereComplex 复杂条件组合

WhereComplex 方法允许在 Join 操作中组合多个 Where 条件,支持复杂的逻辑运算(AND、OR、括号)。这对于构建复杂的多表查询条件非常有用。

9.6.5.1 基本用法

// 组合主表和连接表的条件
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .WhereComplex(w => w.Between(u => u.Age, 18, 60) && w.In(ctx => ctx.As<Order>().Price, 100, 200))
    .GetList();
// 生成 SQL: SELECT * FROM User INNER JOIN "Orders" ON "User"."Id" = "Orders"."UserId" 
// WHERE ("User"."Age" BETWEEN @p0 AND @p1) AND ("Orders"."Price" IN (@p2, @p3))

9.6.5.2 使用 OR 逻辑

// 使用 OR 逻辑组合条件
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .WhereComplex(w => w.Between(u => u.Age, 18, 30) || w.Like(ctx => ctx.As<Order>().ProductName, "%Urgent%"))
    .GetList();
// 生成 SQL: SELECT * FROM User INNER JOIN "Orders" ON "User"."Id" = "Orders"."UserId" 
// WHERE ("User"."Age" BETWEEN @p0 AND @p1) OR ("Orders"."ProductName" LIKE @p2)

9.6.5.3 复杂嵌套条件

// 复杂嵌套条件(使用括号)
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .WhereComplex(w => 
        (w.Between(u => u.Age, 18, 30) && w.Like(u => u.Name, "%John%")) || 
        (w.In(ctx => ctx.As<Order>().Price, 100, 200) && w.NotLike(ctx => ctx.As<Order>().ProductName, "%Old%"))
    )
    .GetList();
// 生成 SQL: SELECT * FROM User INNER JOIN "Orders" ON "User"."Id" = "Orders"."UserId" 
// WHERE (("User"."Age" BETWEEN @p0 AND @p1) AND ("User"."Name" LIKE @p2)) OR 
// (("Orders"."Price" IN (@p3, @p4)) AND ("Orders"."ProductName" NOT LIKE @p5))

9.6.5.4 多表 Join 的 WhereComplex

// 三表 Join 的复杂条件
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .InnerJoin<UserProfile>((ctx, up) => ctx.As<User>().Id == up.UserId)
    .WhereComplex(w => 
        w.Between(u => u.Age, 18, 60) && 
        w.In(ctx => ctx.As<Order>().Price, 100, 200, 300)
    )
    .GetList();

Join WhereComplex 的优势:

  • 支持复杂的逻辑运算(AND、OR、括号)
  • 可以在一个表达式中组合多个表的条件
  • 生成的 SQL 更清晰,可读性更好
  • 适合构建复杂的多表查询条件

9.7 级联 Join(多表 Join)

ORMX 支持无限级联 Join,您可以连接多个表:

9.7.1 三表 Join

连接用户、订单和产品表:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .InnerJoin<Product>((o, p) => o.Id == p.OrderId)
    .GetList<UserOrderProductDto>();

生成的 SQL:

SELECT * FROM User 
INNER JOIN Order ON User."Id" = Order."UserId"
INNER JOIN Product ON Order."Id" = Product."OrderId"

9.7.2 四表 Join

连接更多表:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .InnerJoin<Product>((o, p) => o.Id == p.OrderId)
    .InnerJoin<Category>((p, c) => p.CategoryId == c.Id)
    .GetList<UserOrderProductCategoryDto>();

9.7.3 混合 Join 类型

您可以混合使用不同类型的 Join:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .LeftJoin<Product>((o, p) => o.Id == p.OrderId)
    .GetList<UserOrderProductDto>();

9.8 Join 后的查询操作

Join 后,您可以继续使用各种查询操作:

9.8.1 Where 条件

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Where(ctx => ctx.As<User>().Name.Contains("张"))
    .GetList<UserOrderDto>();

9.8.2 OrderBy 排序

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .OrderByDesc(ctx => ctx.As<Order>().OrderDate)
    .GetList<UserOrderDto>();

9.8.3 Limit/Offset 分页

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Page(pageNumber: 1, pageSize: 20)
    .GetList<UserOrderDto>();

9.8.4 GroupBy 分组

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GroupBy(ctx => ctx.As<User>().Id)
    .Max(ctx => ctx.As<Order>().Amount, "MaxAmount")
    .Sum(ctx => ctx.As<Order>().Amount, "TotalAmount")
    .GetList<UserOrderStats>();

关于聚合函数的详细用法,请查阅聚合函数

9.9 实际应用示例

9.9.1 用户订单查询

查询用户及其订单信息:

public class UserOrderDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string UserEmail { get; set; }
    public int? OrderId { get; set; }
    public decimal? OrderAmount { get; set; }
    public DateTime? OrderDate { get; set; }
}

var result = userTable
    .LeftJoin<Order>((u, o) => u.Id == o.UserId)
    .GetList<UserOrderDto>();

9.9.2 订单产品查询

查询订单及其产品信息:

public class OrderProductDto
{
    public int OrderId { get; set; }
    public decimal OrderAmount { get; set; }
    public int? ProductId { get; set; }
    public string? ProductName { get; set; }
    public decimal? ProductPrice { get; set; }
}

var result = orderTable
    .LeftJoin<Product>((o, p) => o.Id == p.OrderId)
    .GetList<OrderProductDto>();

9.9.3 用户订单产品完整查询

查询用户、订单和产品的完整信息:

public class UserOrderProductDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int? OrderId { get; set; }
    public decimal? OrderAmount { get; set; }
    public DateTime? OrderDate { get; set; }
    public int? ProductId { get; set; }
    public string? ProductName { get; set; }
    public decimal? ProductPrice { get; set; }
}

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .LeftJoin<Product>((o, p) => o.Id == p.OrderId)
    .GetList<UserOrderProductDto>();

9.9.4 用户订单统计

按用户统计订单信息:

public class UserOrderStats
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int OrderCount { get; set; }
    public decimal TotalAmount { get; set; }
    public decimal MaxAmount { get; set; }
    public decimal MinAmount { get; set; }
    public decimal AvgAmount { get; set; }
}

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .GroupBy(ctx => ctx.As<User>().Id)
    .Count(ctx => ctx.As<Order>().Id, "OrderCount")
    .Sum(ctx => ctx.As<Order>().Amount, "TotalAmount")
    .Max(ctx => ctx.As<Order>().Amount, "MaxAmount")
    .Min(ctx => ctx.As<Order>().Amount, "MinAmount")
    .Avg(ctx => ctx.As<Order>().Amount, "AvgAmount")
    .GetList<UserOrderStats>();

9.9.5 最近订单查询

查询每个用户的最近订单:

public class UserRecentOrderDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int? OrderId { get; set; }
    public decimal? OrderAmount { get; set; }
    public DateTime? OrderDate { get; set; }
}

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .OrderByDesc(ctx => ctx.As<Order>().OrderDate)
    .GetList<UserRecentOrderDto>();

9.10 Join 性能优化

9.10.1 使用索引

确保 Join 条件中的字段有索引:

// 为外键创建索引
sqlExecutor.ExecuteNonQuery("CREATE INDEX idx_order_userid ON Order(UserId)");
sqlExecutor.ExecuteNonQuery("CREATE INDEX idx_product_orderid ON Product(OrderId)");

9.10.2 选择合适的 Join 类型

  • INNER JOIN:当只需要匹配的数据时使用
  • LEFT JOIN:当需要主表的所有数据时使用
  • RIGHT JOIN:当需要关联表的所有数据时使用
  • FULL JOIN:当需要两个表的所有数据时使用

9.10.3 限制结果集

使用 Limit/Offset 限制返回的数据量:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Page(pageNumber: 1, pageSize: 20)
    .GetList<UserOrderDto>();

9.10.4 只选择需要的列

使用 Column 方法只选择需要的列:

var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .Column(ctx => new { 
        ctx.As<User>().Id,
        ctx.As<User>().Name,
        ctx.As<Order>().Amount 
    })
    .GetList<UserOrderDto>();

9.11 NoSQL 连接查询

ORMX 不仅支持 SQL 数据库的连接查询,还支持 NoSQL 数据库的连接操作,提供了与 SQL 一致的 API 接口。

9.11.1 NoSQL 连接查询概述

NoSQL 数据库(如 MongoDB)通常不原生支持连接查询,但 ORMX 通过内存计算和映射机制,为 NoSQL 提供了类似 SQL 的连接查询能力。

9.11.2 基本用法

NoSQL 连接查询的基本用法与 SQL 相同:

// NoSQL 内连接
var result = userTable
    .InnerJoin<Order>((u, o) => u.Id == o.UserId)
    .AsFind().GetList();

// NoSQL 左连接
var result = userTable
    .LeftJoin<Order>((u, o) => u.Id == o.UserId)
    .AsFind().GetList();

9.11.3 使用 ctx 上下文

在 NoSQL 中,您同样可以使用 ctx 上下文来访问连接的表:

// 使用 ctx 上下文的 NoSQL 连接查询
var result = userTable
    .InnerJoin<Order>((ctx, o) => ctx.As<User>().Id == o.UserId)
    .Where(ctx => ctx.As<User>().Age > 25 && ctx.As<Order>().Amount > 100)
    .OrderByDesc(ctx => ctx.As<Order>().OrderDate)
    .AsFind().GetList();

9.11.4 复杂 NoSQL 连接查询

您可以在 NoSQL 中使用复杂的连接查询,包括多表连接和复杂条件:

// 多表连接
var result = userTable
    .InnerJoin<Order>((ctx, o) => ctx.As<User>().Id == o.UserId)
    .InnerJoin<Product>((ctx, p) => ctx.As<Order>().Id == p.OrderId)
    .Where(ctx => ctx.As<User>().Age > 25 && ctx.As<Product>().Price > 50)
    .AsFind().GetList();

9.11.5 NoSQL 连接查询的性能考虑

由于 NoSQL 数据库的特性,连接查询的性能可能与 SQL 数据库有所不同:

  1. 内存消耗:NoSQL 连接查询可能需要更多内存来处理数据
  2. 性能影响:对于大规模数据,连接查询可能会影响性能
  3. 最佳实践
    • 对于频繁的连接查询,考虑在数据模型设计时进行适当的冗余
    • 在大规模数据操作时进行性能测试
    • 合理使用索引来优化查询性能

9.11.6 NoSQL 与 SQL 连接查询的区别

特性 SQL 连接查询 NoSQL 连接查询
执行方式 数据库引擎执行 ORMX 内存计算
性能 通常更好 可能较慢,特别是大规模数据
功能支持 完整支持 支持基本和复杂连接
API 接口 统一 与 SQL 相同的 API
适用场景 关系型数据,复杂查询 文档型数据,简单到中等复杂度查询

总结

本章介绍了 ORMX 框架的连表查询功能,包括 INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN 等连接类型的使用方法。ORMX 支持多表连接、复杂 Join 条件和 Join 上下文,提供了灵活的 DTO 映射机制。合理使用 Join 功能,可以高效地查询关联数据。同时,ORMX 也为 NoSQL 数据库提供了连接查询支持,通过内存计算实现类似 SQL 的连接功能。

扩展思考

在复杂的多表连接场景下,如何优化查询性能?是否需要使用索引、查询计划分析等技术?对于大规模数据的连接查询,如何避免内存溢出和性能问题?在分布式系统中,如何实现跨节点的连接查询?这些问题值得在深入使用 ORMX 后进一步思考。