C# LINQ查询技术

LINQ查询技术

LINQ(Language Integrated Query)是一种C#语言中的查询技术,它允许我们在代码中使用类似SQL的查询语句来操作各种数据源。这些数据源可以是集合、数组、数据库、XML文档等等。LINQ提供了一种统一的编程模型,使我们能够使用相同的方式来查询和操作不同类型的数据。


在C#中,LINQ主要由以下几个组成部分:
数据源(Data source):可以是集合、数组、数据库、XML文档等等。
查询变量(Query variable):用于存储查询结果的变量。
查询表达式(Query expression):类似于SQL语句的查询表达式,用于描述查询的逻辑和条件。
查询操作符(Query operator):用于执行各种查询操作,如筛选、排序、分组、投影等等。
查询结果(Query result):查询操作的返回结果。

其中数据源,查询变量,查询结果是必选项,查询表达式,查询操作符是可选项。

分类
LINQ To Entities:查询实体(数据集)
LINQ To Objects:查询对象
LINQ To XML

IQueryable能被查询 AsQueryable() 把 DbSet 转换成IQueryable


LINQ 语法

LINQ 有两种主要的语法:

  1. 查询表达式(Query Syntax):类似 SQL 语法
  2. 方法语法(Method Syntax):使用扩展方法,如 .Where().Select()
class Program
{
  static void Main()
  {
    List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    // 查询表达式
    var evenNumbersQuery = 
      from num in numbers  //forom: 从哪里查(num 查询变量)  in: 在哪个数据源中(numbers 数据源)
      where num > 3 && num < 9  //查询条件
      select num;  //查询结果(是一个集合)

    // 方法语法
    var evenNumbersMethod = numbers.Where(num => num % 2 == 0);

    Console.WriteLine("偶数(查询表达式): " + string.Join(", ", evenNumbersQuery));
    Console.WriteLine("偶数(方法语法): " + string.Join(", ", evenNumbersMethod));
  }
}

多个数据源:

var evenNumbersQuery = 
  from num in numbers 
  form s in student
  where s > 3 && s < 9 
  select s; 
//多个数据源后面的数据源可以使用前面的数据源的数据

常用方法

1. 筛选与过滤

  • Where:筛选满足条件的元素。

    int[] numbers = { 1, 2, 3, 4, 5 }; 
    var evens = numbers.Where(n => n % 2 == 0); // 结果:2, 4
    
  • OfType:筛选特定类型的元素(常用于混合类型集合)。

    object[] mixed = { 1, "two", 3, "four" }; 
    var strings = mixed.OfType<string>(); // 结果:two, four
    

2. 投影与转换

  • Select:将元素转换为新形式。

    string[] words = { "apple", "banana" };
    var upper = words.Select(w => w.ToUpper()); // 结果:APPLE, BANANA
    
  • SelectMany:将嵌套集合展平为一维集合。

    List<string[]> groups = new List<string[]> { new[] { "a", "b" }, new[] { "c" } }; 
    var flat = groups.SelectMany(g => g); // 结果:a, b, c
    

3. 排序

  • OrderBy:按升序排序。

    int[] numbers = { 3, 1, 4, 2 }; 
    var sorted = numbers.OrderBy(n => n); // 结果:1, 2, 3, 4
    
    //方法2.
    var evenNumbersQuery = 
      from num in numbers
      Orderby num ascending  //升序(默认可以省略)
      select num;
    
  • OrderByDescending:按降序排序。

    var desc = numbers.OrderByDescending(n => n); // 结果:4, 3, 2, 1
    
    //方法2.
    var evenNumbersQuery = 
      from num in numbers
      Orderby num descending  //降序
      select num;  
    
  • ThenBy:在已有排序基础上进行次级排序。

    var students = new[] {
      new { Name = "Bob", Age = 20 }, 
      new { Name = "Alice", Age = 20 } 
    }; 
    var ordered = students.OrderBy(s => s.Age).ThenBy(s => s.Name); // 先按年龄,再按姓名
    

4. 分组

  • GroupBy:按键将元素分组。

    string[] words = { "cat", "dog", "car" }; 
    var grouped = words.GroupBy(w => w[0]); // 按首字母分组:c -> {cat, car}, d -> {dog}
    
    //方法2.查询表达式
    var grouped = from s in c.Students
      group s by s.ClassId into g
      //orderby g.Key
      select new { classId = g.Key, count = g.Count() };
    

5. 聚合(计算)

  • Count:计算元素个数。

    int[] numbers = { 1, 2, 3 }; 
    var count = numbers.Count(); // 结果:3
    
  • Sum:计算总和。

    var sum = numbers.Sum(); // 结果:6
    
  • Max/ Min:查找最大/最小值。

    var max = numbers.Max(); // 结果:3 
    var min = numbers.Min(); // 结果:1
    
  • Average:计算平均值。

    var avg = numbers.Average(); // 结果:2
    
  • Aggregate:自定义聚合操作。

    var result = numbers.Aggregate((a, b) => a * b); // 结果:1 * 2 * 3 = 6
    

6. 集合操作

  • Distinct:移除重复元素。

    int[] numbers = { 1, 2, 2, 3 };
    var unique = numbers.Distinct(); // 结果:1, 2, 3
    
  • Union:合并两个集合并去重。

    int[] a = { 1, 2 },  b = { 2, 3 }; 
    var union = a.Union(b); // 结果:1, 2, 3
    
  • Intersect:返回两个集合的交集。

    var intersect = a.Intersect(b); // 结果:2
    
  • Except:返回集合A中不在B中的元素。

    var except = a.Except(b); // 结果:1
    
  • Join:关联

    //方法1.
    var result = collectionA.Join(collectionB,
                                  a => a.Key, 
                                  b => b.Key, 
                                  (a, b) => new { a, b });
    
    //方法2.
    var query = from s in c.Students
      join cr in c.ClassRooms on s.ClassId equals cr.Id
      join u in c.Users on s.CreateUserId equals u.Id
      join u2 in c.Users on s.LastUpdateUserId equals u2.Id into result // 把关联的结果存储到result中
      
      from item in result.DefaultIfEmpty() // 表中找不到匹配项,则item6为空null,这样就不会因为匹配不到数据而丢失该条借阅记录。
    

7. 分页与元素选择

综合下面方法,使用分页:

int pageSize = 10;     // 每页10条
int pageNumber = 1;    // 第1页

var pagedUsers = users
    .OrderBy(u => u.Id) //排序
    .Skip((pageNumber - 1) * pageSize) //跳过前面页的数据
    .Take(pageSize) //取出当前页的数据
    .ToList(); //转换为列表
  • Take:取前N个元素。

    int[] numbers = { 1, 2, 3, 4 }; 
    var top3 = numbers.Take(3); // 结果:1, 2, 3
    
  • Skip:跳过前N个元素。

    • Skip 使用前必须先排序 numbers.OrderByDescending.Skip

var skip2 = numbers.Skip(2); // 结果:3, 4




- First/ FirstOrDefault<font color='MediumSeaGreen'>:返回第一个元素(后者在空集合时返回默认值)。</font>

```csharp
var first = numbers.First(); // 结果:1 
var empty = new int[] {}.FirstOrDefault(); // 结果:0
  • Last/ LastOrDefault:返回最后一个元素。

    var last = numbers.Last(); // 结果:4
    
  • Single/ SingleOrDefault:返回唯一元素(若有多个则抛异常)。

    int[] single = { 1 }; 
    var one = single.Single(); // 结果:1
    

8. 判断与检查

  • Any:检查是否至少有一个元素满足条件。

    int[] numbers = { 1, 2, 3 }; 
    var hasEven = numbers.Any(n => n % 2 == 0); // 结果:true
    
  • All:检查是否所有元素都满足条件。

    var allPositive = numbers.All(n => n > 0); // 结果:true
    
  • Contains:检查集合是否包含某元素。

    var has2 = numbers.Contains(2); // 结果:true
    

9. 执行与转换

  • ToList:将查询结果转换为List<T>并立即执行。

    var list = numbers.Where(n => n > 2).ToList(); // 结果:List {3}
    
  • ToArray:转换为数组。

    var array = numbers.ToArray(); // 结果:int[] {1, 2, 3}
    
  • ToDictionary:转换为字典。

    var dict = students.ToDictionary(s => s.Name, s => s.Score); // 结果:{ "Alice": 85, "Bob": 92 }
    

10. 其他实用方法

  • Concat:连接两个序列。

    int[] a = { 1, 2 }, b = { 3, 4 }; var combined = a.Concat(b); // 结果:1, 2, 3, 4
    
  • Reverse:反转序列。

    var reversed = numbers.Reverse(); // 结果:3, 2, 1
    
  • Zip:将两个序列按位置配对。

    int[] nums = { 1, 2 }, chars = { 'a', 'b' }; 
    var pairs = nums.Zip(chars, (n, c) => $"{n}{c}"); // 结果:1a, 2b
    
Docker ComposeDocker官方提供的工具,用于定义和运行多个容器Docker应用程序。Docker Compose使用YAML文件来配置应用程序的服务,并通过docker-compose命令来启动、停止和管理应用程序的容器。 在docker-compose文件中,可以定义多个服务,每个服务可以包含一个或多个容器。每个服务都有自己的名称、镜像、端口、环境变量等属性。以下是一个简单的docker-compose文件示例: ``` version: '3' services: web: image: nginx:latest ports: - "8080:80" db: image: postgres:latest environment: POSTGRES_PASSWORD: mysecretpassword ``` 在这个docker-compose文件中,定义了两个服务:web和db。web服务使用最新的nginx镜像,并将容器内的80端口映射到主机的8080端口。db服务使用最新的postgres镜像,并设置了一个POSTGRES_PASSWORD环境变量。 除了基本的服务定义外,docker-compose文件还可以包括其他配置选项,例如网络配置、卷配置、依赖关系、扩展性等。 在使用docker-compose命令时,可以使用以下常用命令: - docker-compose up:启动docker-compose文件中定义的所有服务 - docker-compose down:停止docker-compose文件中定义的所有服务 - docker-compose ps:列出docker-compose文件中定义的所有服务和相关的容器 - docker-compose logs:查看docker-compose文件中定义的所有服务的日志 总之,docker-compose文件是定义和管理多个容器Docker应用程序的关键。通过docker-compose文件,可以轻松地定义和配置多个服务,并通过docker-compose命令来启动、停止和管理这些服务的容器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值