Fork me on GitHub
tinylit

Linq语法(二)

Linq语法(二)。

实体一:

public class SimpleDto
{
    public int Id { get; set; }

    public int Code { get; set; }

    public DateTime Date { get; set; }
}

实体二:

public class SimpleRelationDto
{
    public int Id { get; set; }
    public int Code { get; set; }
    public string Name { get; set; }
}

排序:实体一:

public class OrderByHand
{
    public int Id { get; set; }

    public int Code { get; set; }
}

排序:实体二:

public class OrderByHandV2 : IComparable<OrderByHandV2>
{
    public int Id { get; set; }

    public int Code { get; set; }

    public int CompareTo([AllowNull] OrderByHandV2 other)
    {
        if(other is null)
        {
            return 1;
        }

        if (other.Id == Id)
        {
            return Code - other.Code;
        }

        return Id - other.Id;
    }
}

排序:比较类:

public class OrderByHandComparer : IComparer<OrderByHand>
{
    public int Compare([AllowNull] OrderByHand x, [AllowNull] OrderByHand y)
    {
        if (x is null)
        {
            return y is null ? 0 : -1;
        }

        if (y is null)
        {
            return 1;
        }

        if (x.Id == y.Id)
        {
            return x.Code - y.Code;
        }

        return x.Id - y.Id;
    }
}

分组:实体一:

public class GroupByHand
{
    public int Code { get; set; }
}

分组:实体二:

public class GroupByHandV2
{
    public int Code { get; set; }

    public override bool Equals(object obj)
    {
        return obj is GroupByHandV2 v2 && v2.Code == Code;
    }
    public override int GetHashCode()
    {
        return Code.GetHashCode();
    }
}

分组:实体三:

public class GroupByHandV3 : IEquatable<GroupByHandV3>
{
    public int Code { get; set; }

    public bool Equals([AllowNull] GroupByHandV3 other)
    {
        return other != null && other.Code == Code;
    }
}

分组:实体四:

public class GroupByHandV4 : IEquatable<GroupByHandV3>
{
    public int Code { get; set; }

    public bool Equals([AllowNull] GroupByHandV3 other)
    {
        return other != null && other.Code == Code;
    }
    public override int GetHashCode()
    {
        return Code.GetHashCode();
    }
}

分组:比较类:

public class GroupByHandEqualityComparer : IEqualityComparer<GroupByHand>
{
    public bool Equals([AllowNull] GroupByHand x, [AllowNull] GroupByHand y)
    {
        if(x is null)
        {
            return y is null;
        }

        if(y is null)
        {
            return false;
        }

        return x.Code == y.Code;
    }

    public int GetHashCode([DisallowNull] GroupByHand obj) => obj.Code;
}

准备:

List<SimpleDto> simples = new List<SimpleDto>(1000);
List<SimpleRelationDto> simpleRelations = new List<SimpleRelationDto>(500);

for (int i = 0; i < 1000; i++)
{
    simples.Add(new SimpleDto
                {
                    Id = i,
                    Code = i % 10,
                    Date = DateTime.Now
                });

    if (i >= 500) continue;

    simpleRelations.Add(new SimpleRelationDto
                        {
                            Id = i,
                            Code = i % 10,
                            Name = $"第{i}位"
                        });
}

基础语法。

  • 常规。
var linq = simples.Where(x => x.Id > 100); // 过滤条件。
  • 排序。
var linq = simples.OrderByDescending(x => x.Code) // 按Code降序
                .ThenBy(x => x.Id) // 然后,按Id升序。
                .ToList();
  • 分组。
var linq = simples.Where(x => x.Id > 100)
                .GroupBy(x => x.Code) // 分组依据。
                .Select(g => new
                {
                    Code = g.Key,
                    Count = g.Count()
                });
  • 分组统计条件。
var linq = simples.Where(x => x.Id > 100)
                .GroupBy(x => x.Code)
                .Where(x => x.Count() < 5) // 统计条件。
                .Select(g => new
                {
                    Code = g.Key,
                    Count = g.Count()
                });
  • 连接:默认为内连接。
var linq = simples.Join(simpleRelations, x => x.Id, y => y.Id, /* 关联方式。 */ (x, y) => new
            {
                x.Id,
                SimpleCode = x.Code,
                SimpleRelationCode = y.Code
            });
  • 左连接:默认数据。
var simpleRelation = new SimpleRelationDto { Code = 100 };          

var linq = simples.GroupJoin(simpleRelations
                , x => x.Id
                , y => y.Id
                , (x, y) => new { x, g = y })
                .SelectMany(x => x.g.DefaultIfEmpty(simpleRelation) /* 在 simpleRelations 中,找不到与 simples 条件关联的数据时,使用此默认数据。*/, (x, y) => new
                {
                    x.x.Id,
                    SimpleCode = x.x.Code,
                    SimpleRelationCode = y.Code
                });
  • 左连接:默认值。
var linq = simples.GroupJoin(simpleRelations
                , x => x.Id
                , y => y.Id
                , (x, y) => new { x, g = y })
                .SelectMany(x => x.g.DefaultIfEmpty(), (x, y) => new
                {
                    x.x.Id,
                    SimpleCode = x.x.Code,
                    SimpleRelationCode = y == null 
                                            ? 10 // 在 simpleRelations 中,找不到与 simples 条件关联的数据时,使用此默认数据。
                                            : y.Code
                });

高级语法。

  • 按实体排序。
  • 匿名/普通类。

    var results = simples
                      .OrderByDescending(x => new
                      {
                          x.Id,
                          x.Code
                      })
                      .ToList();
    

    注:错误写法!类未实现IComparable接口。

  • IComparable<T>实现类。

    var results = simples
                      .OrderByDescending(x => new OrderByHandV2
                      {
                          Id = x.Id,
                          Code = x.Code
                      })
                      .ToList();
    

    注:不指定比较器时,类必须实现IComparable<T>接口。

  • 指定比较器。

    var results = simples
                      .OrderByDescending(x => new OrderByHand
                      {
                          Id = x.Id,
                          Code = x.Code
                      }, SingletonV7<OrderByHandComparer>.Instance)
                      .ToList();
    

    注:推荐使用!比较器为 null 时,会使用IComparable<T>实现。

  • 按实体分组。
  • 普通类。

    var linq = simples
                      .GroupBy(x => new GroupByHand
                      {
                          Code = x.Code
                      })
                      .Select(x => new
                      {
                          Code = x.Key,
                          Count = x.Count()
                      });
    

    注:错误写法!

  • 匿名类。

    var linq = simples
                      .GroupBy(x => new
                      {
                          x.Code
                      })
                      .Select(x => new
                      {
                          Code = x.Key,
                          Count = x.Count()
                      });
    

    注:匿名类默认重写了Equals(object obj)GetHashCode()方法。

  • IEquatable<T>实现类。

    var linq = simples
                      .GroupBy(x => new GroupByHandV3
                      {
                          Code = x.Code
                      })
                      .Select(x => new
                      {
                          Code = x.Key,
                          Count = x.Count()
                      });
    

    注:错误写法!除实现接口外,还需重写GetHashCode()方法。

  • IEquatable<T>实现类并重写GetHashCode()方法。

    var linq = simples
                      .GroupBy(x => new GroupByHandV4
                      {
                          Code = x.Code
                      })
                      .Select(x => new
                      {
                          Code = x.Key,
                          Count = x.Count()
                      });
    
  • 指定比较器。

    var linq = simples
                      .GroupBy(x => new GroupByHand
                      {
                          Code = x.Code
                      }, SingletonV7<GroupByHandEqualityComparer>.Instance)
                      .Select(x => new
                      {
                          Code = x.Key,
                          Count = x.Count()
                      });
    

    注:推荐使用!

posted @ 2021-10-26 16:31  影子和树  阅读(38)  评论(0编辑  收藏  举报