【C#】【LINQ】语句简单应用

本文介绍了Linq在处理对象集合、DataTable、分组、联接和联表嵌套分组等场景中的应用。示例包括对List对象集合的查询、对DataTable的过滤、按特定字段分组以及联接操作。还展示了如何通过Linq进行复杂的数据统计,如新增用户、活跃用户和留存用户的计算。

1.对对象集合的简单运用

//定义有实体类A,其中类成员变量都为公有,分别为string field1 和 int field2
//假设List为A的对象集合,即List类型为List<A>,则可以使用Linq语句进行查询
from n in List
where n.field1 == "10" && n.field2 > 5
select n
//以上代码查询结果为查询List对象集合中,成员field1 的值等于字符串"10"且成员field2的值大于数字5的对象集合

2.对DataTable的简单运用


string tempStr = "1,2";
//获取ble中temp列不存在于tempStr字符串中的行
DataTable ble = 获取需要操作的DataTable数据
DataTable temp = (from t in ble.AsEnumerable()
                              where !tempStr.Contains(t.Field<string>("temp"))
                              select t).CopyToDataTable();

3.分组的简单运用 

Linq分组分两种,⼀种是表分组汇总,另⼀种是List<>分组汇总。下⾯分别举例说明两种分组汇总。
第⼀种,表的分组汇总:
DataTable table = new DataTable();
table.Columns.Add("列名1", Type.GetType("System.Int32"));
table.Columns.Add("列名2", Type.GetType("System.Int32"));
table.Columns.Add("列名3", Type.GetType("System.String"));
table.Columns.Add("列名4", Type.GetType("System.String"));
table.Columns.Add("列名5", Type.GetType("System.String"));
table.Columns.Add("数值或⾦额列名", Type.GetType("System.String"));
//为table表赋值
……
//按[列名2]分组汇总
var dtSummary = from q in table.AsEnumerable()
                          group q by new { 列名2= q.Field<int>("列名2")} into g
                          select new
                          {
                              列名2= g.Key.列名2,
                              数值或⾦额汇总列名= g.Sum(a => a.Field<decimal>("数值或⾦额列名"))
                          };
第⼆种,List<>分组汇总:
var listSummary = from p in List<实体>
                                       group p by new { 属性1 = p.属性1 } into g
                                       select new
                                       {
                                           属性1 = g.Key.属性1 ,
                                           数值或⾦额汇数值或⾦额汇总= g.Sum(a => a.数值或⾦额属性)
                                       };
//p为实体别名,代表List中的实体,
//
int x = 2
var listSummary = (from p in List<实体>
                  //条件查询List中属性1的值等于x的数据
                  where p.属性1 == x
                  //通过p.属性1分组,输出为g
                  group p by new { 属性1 = p.属性1 } into g
                  //此处可以输出为类,不写类名为直接输出为object类型,等同于 new {},
                  select new
                  {
                      属性1 = g.Key.属性1 ,
                      数值或⾦额汇数值或⾦额汇总= g.Sum(a => a.数值或⾦额属性),
                      数据数量 = g.Count()
                  }).OrderByDescending(a => a.属性1).ToList();//输出的内容用属性1进行倒序排序并输出为集合,此处需要用小括号将linq内容括起来,才能使用排序和输出集合方法

4.联接的简单运用

有表结构:

id=baseId,需要输出结果:

LINQ代码如下 

//表一类
public class table_a{
    public int id {get;set;}
    public string value {get;set;}
}
//表2类
public class table_b{
    public int baseId {get;set;}
    public string name{get;set;}
}

var list =  from a in List<table_a>
            join b in List<table_b> on a.id equals b.baseId 
            select new
            {
                id=a.id,
                value=a.value,
                name = b.name
            } ;//list为需要的输出结果
                         

5.联表嵌套分组应用

模拟场景:需要按照县区统计系统内各县区用户数量,新增用户数量(操作日志只有一条的用户)、活跃用户数量(近7天有4天登陆的用户)、留存用户数量(累计3天登陆的用户)。

示例代码:

//用户登录日志类
public class LogLoginEntity 
{
    public long BaseCreatorId{ get; set; }//用户表主键ID
    public DateTime BaseCreateTime{ get; set; }//登录时间
    public string ip { get; set; }//登录IP
}
//用户类
public class UserEntity{
    public long Id {get;set;}//用户主键ID
    public string AreaCode {get;set;}//用户所属行政区划编号
    public string RealName {get;set;}//用户真实姓名
}
//行政区划类
public class AreaEntity{
    public long Id {get;set;}//主键ID
    public string AreaCode {get;set;}//行政区划编号
    public string AreaCode {get;set;}//父级行政区划编号
    public string AreaName {get;set;}//行政区划名称
}
//用户报表类
private class userReport {
    public string Id { get; set; }
    public string Name { get; set; }//用户姓名
    public List<GroupInfo> GroupData { get; set; }//日志分组信息
}
//分组信息类
public class treeInfo
{
    public string text { get; set; }//登陆时间
    public string value { get; set; }//登陆次数
}

//业务代码
public object GetReportData()
{
    object result;
    try
    {
        //获取系统用户列表
        List<UserEntity> userList = GetUserList()//自行编写获取集合方法
        //获取用户登录日志列表    
        List<LogLoginEntity > loginLogList = GetLoginLogList()//自行编写获取集合方法
        //获取行政区划列表
        List<AreaEntity> areaList = GetAreaList()//自行编写获取集合方法

        //用户数量
        List<string> userCount = new List<string>();
        //新增用户(操作日志只有一条的用户)
        List<string> newUserCount = new List<string>();
        //活跃用户(近7天有4天登陆的用户)
        List<string> activeUserCount = new List<string>();
        //留存用户(累计3天登陆的用户)
        List<string> retainedUserCount = new List<string>();
        DateTime date = DateTime.Now.AddDays(-6);//从当前日期算起取7天前的日期
        //循环行政区划列表
        areaList.ForEach(a => {
            //获取所属当前行政区划用户列表
            List<UserEntity> tempUserList = userList.Where(user => user.AreaCode == a.AreaCode).ToList();
            //添加当前地区用户数量
            userCount.Add(tempUserList.Count.ToString());
            //Linq查询数据
            List<userReport> tempNewUserList = (from log in loginLogList//以日志表为主表
                                                join user in tempUserList on log.BaseCreatorId equals  user.Id//联接用户表通过主外键
                                                where user.AreaCode == a.AreaCode//获取联表数据中所属当前行政区划数据
                                                group new {
//创建分组集合信息,由用户真实姓名和登陆时间组成
                                                              RealName = user.RealName,
                                                              BaseCreateTime = log.BaseCreateTime
                                                }  by new { Id = user.Id//用用户ID对数据进行分组 } into g
                                                select new userReport()
                                                {//创建报表类实体
                                                    Id = g.Key.Id.ToString(),//用来分组的字段
                                                    Name = g.Max(r => r.RealName),//分组集合g姓名最大值(姓名相同,通过方法获取,类似SQL中的聚合函数)
                                                    //对当前用户的分组集合g再次进行分组
                                                    GroupData = (from groupMod in g
                                                                 group groupMod by new { LoginTime = ((DateTime)groupMod.BaseCreateTime).ToString("yyyy-MM-dd") } into g1//使用BaseCreateTime的字符串格式进行分组,
                                                                 select new treeInfo()
                                                                 {
                                                                     text = g1.Key.LoginTime,//用来分组的字段
                                                                     value = g1.Count().ToString()//分组集合g1数据数量
                                                                 }).ToList()
                                                }).ToList();
            //添加新增用户数量,通过查询用户日志分组信息数量如果只有一条数据判断为新增用户
            newUserCount.Add(tempNewUserList.Where(user => user.GroupData.Count == 1).Count().ToString());
            //添加活跃用户数量,通过查询用户的日志分组信息中登陆时间日期大于设定日期的数据数量大于等于4判断为活跃用户
            activeUserCount.Add(tempNewUserList.
            Where(user => user.GroupData.
            Where(group => DateTime.Parse(group.text) >= date).Count() >= 4).Count().ToString());
            //添加留存用户数量,通过查询用户的日志分组信息中数据数量大于等于3判断为留存用户
            retainedUserCount.Add(tempNewUserList.Where(user => user.GroupData.Count >= 3).Count().ToString());
        });
        result= new {
            totalCount = userList.Count,
            userCount = userCount,
            newUserCount = newUserCount,
            activeUserCount = activeUserCount,
            retainedUserCount = retainedUserCount,
            areaList = areaList
        };
    }
    catch (Exception ex)
    {
    }

    return (result);//返回结果
}

 

<think>好的,用户让我介绍C#LINQ语句。首先,我需要确定用户的基础,可能他们已经有C#的基本知识,但LINQ是相对高级的内容,所以得从基础讲起。 LINQ全称是Language Integrated Query,集成在语言中的查询功能。用户可能知道SQL,但LINQ的不同之处在于它可以直接在C#代码里写查询,支持多种数据源,比如集合、数据库、XML等。这里需要分点说明,结构清晰。 接下来,用户可能需要了解LINQ的两种语法形式:查询表达式和方法语法。查询表达式类似SQL,更易读,而方法语法使用扩展方法,比如Where、Select,可能更灵活。应该举例说明两种写法,让用户对比理解。 然后,要介绍LINQ的核心概念,比如延迟执行。这个很重要,因为有时候用户可能会遇到查询不立即执行的情况,导致意想不到的结果。比如,在修改数据源后,查询结果可能会变化,这时候需要解释IEnumerable和IQueryable的区别,以及如何强制立即执行,比如通过ToList()。 还要覆盖常见的LINQ操作符,比如筛选Where、排序OrderBy、分组GroupBy、连接Join、聚合函数Count、Sum等。每个部分给出简单例子,帮助用户快速上手。比如,Where的例子可以用一个整数集合过滤偶数,OrderBy的例子排序字符串长度。 另外,用户可能想知道LINQ应用场景,比如处理集合数据、数据库查询(配合Entity Framework)、XML处理等。需要提到不同的LINQ提供程序,比如LINQ to Objects、LINQ to SQL、LINQ to Entities,说明它们的适用环境。 可能用户会遇到的问题,比如性能问题,特别是延迟执行导致多次查询,或者复杂查询的效率。这时候可以建议使用合适的索引,或者适时强制立即执行,减少重复查询的开销。 最后,总结一下LINQ的优势,比如代码简洁、类型安全、可组合性等,同时提醒注意事项,比如理解延迟执行,避免不必要的性能损耗。确保用户有一个全面的认识,同时能实际应用。</think>C# LINQ(Language Integrated Query)是集成在.NET中的强类型查询技术,通过统一的语法实现跨数据源查询。以下是分步解析: 一、基础结构 1. 数据源:必须实现`IEnumerable<T>`接口 ```csharp List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; ``` 2. 查询表达式(类SQL语法): ```csharp var evenNumbers = from num in numbers where num % 2 == 0 select num; ``` 3. 方法语法(链式调用): ```csharp var evenNumbers = numbers.Where(num => num % 2 == 0); ``` 二、核心操作符 1. 筛选(WHERE): ```csharp var adults = people.Where(p => p.Age >= 18); ``` 2. 投影(SELECT): ```csharp var names = people.Select(p => p.Name); ``` 3. 排序: $$ \text{升序:OrderBy(), 降序:OrderByDescending()} $$ ```csharp var ordered = products.OrderBy(p => p.Price); ``` 4. 分组(GROUP BY): ```csharp var groups = from p in products group p by p.Category into g select new { Category = g.Key, Items = g }; ``` 三、延迟执行机制 1. 查询在枚举时执行 2. 立即执行方法: - `ToList()` - `ToArray()` - `Count()` - `First()` 四、高级应用 1. 连接查询(JOIN): ```csharp var query = from emp in employees join dept in departments on emp.DeptId equals dept.Id select new { emp.Name, dept.Name }; ``` 2. 聚合函数: $$ \text{Sum(), Average(), Max(), Min()} $$ ```csharp var total = orders.Sum(o => o.Amount); ``` 五、性能优化建议 1. 避免嵌套循环查询 2. 对大数据集优先使用`AsParallel()` 3. 在数据库场景中保持IQueryable 注意:LINQ to SQL/Entity Framework会将查询转换为SQL语句,而LINQ to Objects直接在内存中执行。 典型应用场景: 1. 集合数据处理 2. 数据库查询(EF Core) 3. XML文档解析 4. 异步流处理(配合async/await) 示例综合应用: ```csharp var result = dbContext.Orders .Where(o => o.OrderDate.Year == 2023) .GroupBy(o => o.CustomerId) .Select(g => new { CustomerId = g.Key, Total = g.Sum(o => o.Amount), Avg = g.Average(o => o.Amount) }) .OrderByDescending(x => x.Total) .Take(10) .ToList(); ``` 通过LINQ可以实现声明式编程,使代码更简洁且类型安全,但需注意合理使用以避免性能问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值