SQL到LINQ转换终极指南:.NET开发者必知的10个核心查询

在.NET生态中,LINQ(Language Integrated Query)是连接业务逻辑与数据库操作的桥梁。本文将通过10个典型SQL查询案例,结合深度代码注释性能对比分析,手把手教你从SQL语法无缝过渡到LINQ的声明式编程范式。


第一章:基础查询转换

1.1 SELECT查询转换

SQL版本:
SELECT ProductID, ProductName, Price 
FROM Products 
WHERE Category = 'Electronics';
LINQ版本:
// 使用查询语法
var query = from p in dbContext.Products
            where p.Category == "Electronics"
            select new 
            {
                p.ProductID,
                p.ProductName,
                p.Price
            };

// 使用方法语法
var methodQuery = dbContext.Products
    .Where(p => p.Category == "Electronics")
    .Select(p => new 
    {
        p.ProductID,
        p.ProductName,
        p.Price
    });

// 执行查询(强制执行)
var result = query.ToList(); // ① 强制执行查询

1.2 排序与分页

SQL版本:
SELECT * FROM Orders 
ORDER BY OrderDate DESC 
LIMIT 10 OFFSET 20;
LINQ版本:
var pagedResult = dbContext.Orders
    .OrderByDescending(o => o.OrderDate) // ① 排序
    .Skip(20) // ② 跳过前20条
    .Take(10) // ③ 取10条
    .ToList();

第二章:连接查询(JOIN)

2.1 内连接(INNER JOIN)

SQL版本:
SELECT o.OrderID, p.ProductName, od.Quantity 
FROM Orders o 
INNER JOIN OrderDetails od ON o.OrderID = od.OrderID 
INNER JOIN Products p ON od.ProductID = p.ProductID;
LINQ版本:
var joinedQuery = from o in dbContext.Orders
                  join od in dbContext.OrderDetails 
                  on o.OrderID equals od.OrderID
                  join p in dbContext.Products 
                  on od.ProductID equals p.ProductID
                  select new 
                  {
                      o.OrderID,
                      p.ProductName,
                      od.Quantity
                  };

2.2 左外连接(LEFT JOIN)

SQL版本:
SELECT u.UserID, u.UserName, o.OrderID 
FROM Users u 
LEFT JOIN Orders o ON u.UserID = o.UserID;
LINQ版本:
var leftJoinQuery = from u in dbContext.Users
                    join o in dbContext.Orders 
                    on u.UserID equals o.UserID 
                    into ordersGroup // ① 使用into创建组
                    from o in ordersGroup.DefaultIfEmpty() // ② 处理空值
                    select new 
                    {
                        u.UserID,
                        u.UserName,
                        OrderID = o?.OrderID // ③ 安全访问
                    };

第三章:聚合与分组

3.1 分组统计(GROUP BY)

SQL版本:
SELECT Category, COUNT(*) AS ProductCount 
FROM Products 
GROUP BY Category 
HAVING COUNT(*) > 5;
LINQ版本:
var groupedQuery = from p in dbContext.Products
                   group p by p.Category into categoryGroup
                   where categoryGroup.Count() > 5 // ① HAVING条件
                   select new 
                   {
                       Category = categoryGroup.Key,
                       ProductCount = categoryGroup.Count()
                   };

3.2 聚合函数(MAX, MIN, AVG)

SQL版本:
SELECT MAX(Price) AS MaxPrice, 
       MIN(Price) AS MinPrice, 
       AVG(Price) AS AvgPrice 
FROM Products;
LINQ版本:
var aggregateResult = new 
{
    MaxPrice = dbContext.Products.Max(p => p.Price),
    MinPrice = dbContext.Products.Min(p => p.Price),
    AvgPrice = dbContext.Products.Average(p => p.Price)
};

第四章:子查询与存在性检查

4.1 子查询(Subquery)

SQL版本:
SELECT * FROM Orders 
WHERE OrderID IN (SELECT OrderID FROM OrderDetails WHERE Quantity > 10);
LINQ版本:
var subQuery = dbContext.OrderDetails
    .Where(od => od.Quantity > 10)
    .Select(od => od.OrderID);

var result = dbContext.Orders
    .Where(o => subQuery.Contains(o.OrderID)) // ① 包含子查询
    .ToList();

4.2 存在性检查(EXISTS)

SQL版本:
SELECT * FROM Categories 
WHERE EXISTS (SELECT 1 FROM Products 
              WHERE Products.CategoryID = Categories.CategoryID);
LINQ版本:
var existsQuery = dbContext.Categories
    .Where(c => dbContext.Products
        .Any(p => p.CategoryID == c.CategoryID)) // ① Any实现EXISTS
    .ToList();

第五章:复杂查询模式

5.1 多条件动态查询

SQL版本:
SELECT * FROM Employees 
WHERE (Department = 'Sales' OR Department = 'Marketing') 
AND HireDate BETWEEN '2020-01-01' AND '2023-12-31';
LINQ版本:
var dynamicQuery = dbContext.Employees
    .Where(e => new[] { "Sales", "Marketing" }.Contains(e.Department) // ① IN条件
        && e.HireDate >= new DateTime(2020, 1, 1) 
        && e.HireDate <= new DateTime(2023, 12, 31));

5.2 跨数据库关联(CROSS JOIN)

SQL版本:
SELECT c.CategoryName, p.ProductName 
FROM Categories c 
CROSS JOIN Products p 
WHERE c.CategoryID = p.CategoryID;
LINQ版本:
var crossJoinQuery = from c in dbContext.Categories
                     from p in dbContext.Products // ① 无条件连接
                     where c.CategoryID == p.CategoryID
                     select new { c.CategoryName, p.ProductName };

第六章:性能与优化

6.1 延迟执行(Lazy Execution)

var query = dbContext.Products.Where(p => p.Price > 100); // ① 未执行
query = query.OrderBy(p => p.Name); // ② 构建查询表达式树
var result = query.ToList(); // ③ 触发数据库查询

6.2 即时执行(Eager Loading)

// 强制即时执行
var cachedData = dbContext.Orders
    .Include(o => o.Customer) // ① 预加载关联实体
    .ToArray(); // ② 触发立即查询

第七章:高级技巧

7.1 原生SQL与LINQ混合使用

var sqlQuery = dbContext.Database.SqlQuery<Product>(
    "SELECT * FROM Products WHERE Price > @0", 200);

var linqQuery = dbContext.Products
    .Where(p => p.Price > 200); // ① 两种方式对比

7.2 动态查询构建

var query = dbContext.Products.AsQueryable();

if (!string.IsNullOrEmpty(searchTerm))
{
    query = query.Where(p => p.Name.Contains(searchTerm));
}

if (minPrice.HasValue)
{
    query = query.Where(p => p.Price >= minPrice.Value);
}

var result = query.ToList();

第八章:常见错误与调试技巧

8.1 转义字符问题

// 错误写法:直接拼接字符串
var query = dbContext.Products.Where(p => p.Name == "O'Reilly"); // ① 报错

// 正确写法:使用参数化查询
var safeQuery = dbContext.Products.Where(p => p.Name == "O'Reilly");

8.2 调试查询语句

// 使用日志记录查看生成的SQL
using (var dbContext = new MyDbContext())
{
    dbContext.Database.Log = Console.WriteLine; // ① 输出SQL语句
    var result = dbContext.Products.ToList();
}

第九章:LINQ to SQL vs Entity Framework

9.1 数据库映射差异

// LINQ to SQL映射
[Table(Name = "dbo.Products")]
public class Product
{
    [Column(IsPrimaryKey = true)]
    public int ProductID { get; set; }
}

// Entity Framework映射
public class Product
{
    [Key]
    public int ProductID { get; set; }
}

9.2 查询优化对比

// EF Core的Include优化
var orders = dbContext.Orders
    .Include(o => o.Customer)
    .ThenInclude(c => c.Addresses)
    .ToList();

// LINQ to SQL的LoadWith
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Order>(o => o.Customer);
dbContext.LoadOptions = dlo;

第十章:未来趋势与扩展

10.1 C# 12的LINQ增强

// 预计特性:管道表达式增强
var result = dbContext.Products
    | where p => p.Price > 100 
    | select p => p.Name 
    | toList();

10.2 异步查询优化

// 异步执行
var asyncResult = await dbContext.Products
    .Where(p => p.Category == "Electronics")
    .ToListAsync();

结语:从SQL到LINQ的思维跃迁

通过本文的10个核心案例,开发者可以掌握:

  • 语法映射:将传统SQL思维转化为LINQ的声明式语法
  • 性能优化:理解延迟执行与表达式树的底层机制
  • 复杂场景:处理多表关联、动态查询等高级需求
  • 工具链:结合EF Core、LINQPad等工具提升开发效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值