LINQ(Language Integrated Query)与数据库的结合主要通过 LINQ to SQL
或 Entity Framework
来实现。这两种技术允许开发者使用 LINQ 查询数据库中的数据,类似于查询内存中的对象。这里以 Entity Framework
(EF)为主要示例,因为它是目前最流行的 ORM(对象关系映射)工具之一,并广泛支持 LINQ 查询数据库。
一、什么是 Entity Framework(EF)
Entity Framework 是微软提供的一个对象关系映射(ORM)框架,允许开发者使用面向对象的方式与数据库交互。EF 可以将数据库中的表映射为 C# 对象,并使用 LINQ 查询这些对象来执行数据库操作。
EF 有两种常用的模型构建方式:
- Code First:使用代码定义数据模型,数据库根据代码自动生成。
- Database First:从现有数据库生成数据模型,适用于已有数据库的场景。
二、使用 LINQ 查询数据库的基本步骤
1. 准备工作
首先,确保已经安装并配置了 Entity Framework。可以通过 NuGet 安装 Entity Framework 包。
Install-Package EntityFramework
创建一个数据模型。假设我们有一个名为 Customer
的表,其结构如下:
Id | Name | City |
---|---|---|
1 | Alice | New York |
2 | Bob | Los Angeles |
3 | Charlie | New York |
2. 创建数据模型
使用 Code First 方式创建数据模型。首先定义实体类和上下文类:
// Customer.cs
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
// AppDbContext.cs
using System.Data.Entity;
public class AppDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
}
3. 生成数据库
在 Code First
模式下,可以通过 EF 自动生成数据库。
using (var context = new AppDbContext())
{
if (!context.Customers.Any())
{
context.Customers.Add(new Customer { Name = "Alice", City = "New York" });
context.Customers.Add(new Customer { Name = "Bob", City = "Los Angeles" });
context.Customers.Add(new Customer { Name = "Charlie", City = "New York" });
context.SaveChanges();
}
}
三、使用 LINQ 查询数据库
1. 简单查询
使用 LINQ 查询数据库中的数据,获取所有客户信息。
using (var context = new AppDbContext())
{
var customers = from c in context.Customers
select c;
foreach (var customer in customers)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
上述查询使用了 LINQ 的查询语法,也可以使用方法语法来完成相同的操作:
using (var context = new AppDbContext())
{
var customers = context.Customers.ToList();
foreach (var customer in customers)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
2. 带条件的查询
使用 Where
过滤数据,查询所有在 “New York” 城市的客户。
using (var context = new AppDbContext())
{
var customersInNewYork = from c in context.Customers
where c.City == "New York"
select c;
foreach (var customer in customersInNewYork)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
方法语法实现相同的操作:
using (var context = new AppDbContext())
{
var customersInNewYork = context.Customers
.Where(c => c.City == "New York")
.ToList();
foreach (var customer in customersInNewYork)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
3. 投影查询
使用 Select
操作符,只选择客户的名字。
using (var context = new AppDbContext())
{
var customerNames = from c in context.Customers
select c.Name;
foreach (var name in customerNames)
{
Console.WriteLine(name);
}
}
方法语法的实现方式:
using (var context = new AppDbContext())
{
var customerNames = context.Customers
.Select(c => c.Name)
.ToList();
foreach (var name in customerNames)
{
Console.WriteLine(name);
}
}
4. 排序查询
可以使用 OrderBy
或 OrderByDescending
对数据进行排序。下面的例子按客户名字进行升序排序:
using (var context = new AppDbContext())
{
var sortedCustomers = from c in context.Customers
orderby c.Name
select c;
foreach (var customer in sortedCustomers)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
方法语法实现:
using (var context = new AppDbContext())
{
var sortedCustomers = context.Customers
.OrderBy(c => c.Name)
.ToList();
foreach (var customer in sortedCustomers)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
5. 分组查询
使用 GroupBy
根据某个字段分组,比如按城市分组客户。
using (var context = new AppDbContext())
{
var groupedCustomers = from c in context.Customers
group c by c.City into cityGroup
select cityGroup;
foreach (var group in groupedCustomers)
{
Console.WriteLine($"City: {group.Key}");
foreach (var customer in group)
{
Console.WriteLine($" {customer.Name}");
}
}
}
方法语法的实现方式:
using (var context = new AppDbContext())
{
var groupedCustomers = context.Customers
.GroupBy(c => c.City)
.ToList();
foreach (var group in groupedCustomers)
{
Console.WriteLine($"City: {group.Key}");
foreach (var customer in group)
{
Console.WriteLine($" {customer.Name}");
}
}
}
6. 连接查询
可以使用 Join
连接两个不同的表。假设我们有另一个表 Order
,表示客户的订单。
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string Product { get; set; }
public int Quantity { get; set; }
}
查询所有客户及其订单信息:
using (var context = new AppDbContext())
{
var query = from c in context.Customers
join o in context.Orders on c.Id equals o.CustomerId
select new { c.Name, o.Product, o.Quantity };
foreach (var result in query)
{
Console.WriteLine($"{result.Name} ordered {result.Quantity} of {result.Product}");
}
}
四、执行 SQL 查询
除了使用 LINQ 查询数据,Entity Framework 还支持直接执行原生 SQL 查询:
using (var context = new AppDbContext())
{
var customers = context.Database.SqlQuery<Customer>("SELECT * FROM Customers WHERE City = 'New York'").ToList();
foreach (var customer in customers)
{
Console.WriteLine($"{customer.Name} - {customer.City}");
}
}
五、延迟执行与立即执行
LINQ 查询的特点之一是延迟执行,即查询不会在定义时执行,而是在遍历或调用方法(如 ToList()
、Count()
等)时执行。这有助于提高查询性能。
var query = context.Customers.Where(c => c.City == "New York"); // 查询未执行
var resultList = query.ToList(); // 查询在此时执行
六、总结
- LINQ 提供了一个统一的数据查询语法,可以用来查询数据库、内存集合、XML 等数据源。
- Entity Framework 结合 LINQ 提供了强大的 ORM 功能,简化了数据库操作。
- 查询表达式和方法语法各有特点,可以混合使用。
- 延迟执行有助于提高性能,但需要注意可能的副作用。