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() });
注:推荐使用!
愿您好运,如影随形!