This page shows the typical SQL shapes produced by common LiteOrm patterns for debugging, performance analysis, and database adaptation.
Notes:
SqlBuilder, database dialect, pagination syntax, and registered extensions.var users = await userService.SearchAsync(u => u.Age >= 18 && u.UserName!.StartsWith("A"));
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime]
FROM [Users] [T0]
WHERE [T0].[Age] >= @0 AND [T0].[UserName] LIKE @1
using static LiteOrm.Common.Expr;
var expr = (Prop("Age") >= 18) & Prop("UserName").StartsWith("A");
var users = await userService.SearchAsync(expr);
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime]
FROM [Users] [T0]
WHERE [T0].[Age] >= @0 AND [T0].[UserName] LIKE @1
var page = await userService.SearchAsync(
q => q.Where(u => u.Age >= 18)
.OrderByDescending(u => u.CreateTime)
.Skip(20).Take(10)
);
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime]
FROM [Users] [T0]
WHERE [T0].[Age] >= @0
ORDER BY [T0].[CreateTime] DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Older databases or custom dialects may use ROW_NUMBER() or database-specific pagination syntax.
using static LiteOrm.Common.Expr;
var users = await userService.SearchAsync(
u => Exists<Department>(d => d.Id == u.DeptId && d.Name == "R&D")
);
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime]
FROM [Users] [T0]
WHERE EXISTS (
SELECT 1 FROM [Departments] [T1] WHERE [T1].[Id] = [T0].[DeptId] AND [T1].[Name] = @0
)
using static LiteOrm.Common.Expr;
var expr = ExistsRelated<DepartmentView>(Prop("Name") == "R&D");
var users = await userService.SearchAsync(expr);
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime]
FROM [Users] [T0]
WHERE EXISTS (
SELECT 1 FROM [Departments] [T1] WHERE [T1].[Id] = [T0].[DeptId] AND [T1].[Name] = @0
)
If written as:
using static LiteOrm.Common.Expr;
var expr = ExistsRelated<DepartmentView>(Prop("Name").StartsWith("R&D")).Not();
The SQL becomes NOT EXISTS (...).
var users = await viewService.SearchAsync(u => u.DeptName == "R&D");
Typical SQL shape:
SELECT [T0].[Id], [T0].[UserName], [T0].[Age], [T0].[DeptId], [T0].[CreateTime],
[T1].[Name] AS [DeptName]
FROM [Users] [T0]
LEFT JOIN [Departments] [T1] ON [T1].[Id] = [T0].[DeptId]
WHERE [T1].[Name] = @0
var sales = await salesService.SearchAsync(
s => s.Amount > 100,
tableArgs: new[] { "202411" }
);
Typical SQL shape:
SELECT [T0].[Id], [T0].[ProductId], [T0].[Amount], [T0].[SaleTime]
FROM [Sales_202411] [T0]
WHERE [T0].[Amount] > @0
await userService.BatchInsertAsync(users);
Typical SQL shape:
INSERT INTO [Users] ([UserName], [Age], [CreateTime]) VALUES (@0, @1, @2), (@3, @4, @5), (@6, @7, @8)
When IBulkProvider is registered, batch insert may use native bulk interfaces instead of regular SQL:
SqlBulkCopyMySqlBulkCopyusing static LiteOrm.Common.Expr;
await userService.UpdateAsync(
Update<User>()
.Set("Age", Prop("Age") + 1)
.Where(Prop("DeptId") == 2)
);
Typical SQL shape:
UPDATE [Users] SET [Age] = [Age] + 1 WHERE [DeptId] = @0
using static LiteOrm.Common.Expr;
var amountSum = Func("SUM", Prop("Amount"))
.Over([Prop("ProductId")], [Prop("SaleTime").Asc()]);
var selectExpr = From<SalesRecord>("202411")
.Select("Id", "ProductId", "ProductName", "Amount", "SaleTime")
.SelectMore(new SelectItemExpr(amountSum, "ProductTotal"));
var results = await salesDAO
.SearchAs<SalesWindowView>(selectExpr)
.ToListAsync();
Typical SQL shape:
SELECT [T0].[Id], [T0].[ProductId], [T0].[ProductName], [T0].[Amount], [T0].[SaleTime],
SUM([T0].[Amount]) OVER (PARTITION BY [T0].[ProductId] ORDER BY [T0].[SaleTime] ASC) AS [ProductTotal]
FROM [Sales_202411] [T0]
Actual window function SQL depends on your registered function handlers and database dialect.
SessionManager.Current?.SqlStack provides the SQL executed in the current session.SqlStack keeps up to 10 recent SQL statements and clears after each Service method call.