从 linq 查询中删除重复项

时间:2021-06-19 12:31:45

标签: c# linq

我用ef core从数据库中读取信息

var dbQuery = db.ManifestTable.Select(x => new
{
    x.Id,
    x.Uri,
    x.Code,
    x.Version
});
var data = await dbQuery.ToListAsync();

return data
    .GroupBy(x => x.Id)
    .OrderBy(x => x.Key)
    .Select(g => new myModel
    {
        Id = g.Key,
        Uri = g.Select(x => x.Uri).First(),
        Code = g.Select(x => x.Code).First(),
        myVersion = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }).OrderByDescending(x => x.Version).First(),
        Versions = g.Select(x => new myVersion { Version = x.Version, Uri = x.Uri }).OrderByDescending(x => x.Version).ToList()
    });

问题是版本字段中有重复项

我尝试使用 Distinct 方法,但没有用 如何从“版本”字段中删除重复的版本?

1 个答案:

答案 0 :(得分:0)

对于 Distinct,您需要实现 IEqualityComparer 接口。一个 C#9 代码示例,它位于一个简单的列表中(不是您的数据,只是一个简单的模型)但应该适合您。请注意,我使用了一个单元测试项目来验证比较器是否有效。

我会首先考虑@Barns 在GroupBy 上的推荐。

如果可能,另一个想法是在业务规则允许的情况下防止输入重复项。

容器

public class Resident
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

比较者

using System;
using System.Collections.Generic;

/*
 * Each class should be in their own class file, here they are
 * in one file for easily comparing (excuse the pun) implementation
 * of a string comparer vs a int comparer.
 */
namespace QueryOperatorsTest.Classes
{
    /// <summary>
    /// Comparer against Name property
    /// </summary>
    public class ResidentNameComparer : IEqualityComparer<Resident>
    {
        public bool Equals(Resident x, Resident y) => 
            string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
        public int GetHashCode(Resident obj) => obj.Name.GetHashCode();
    }
    /// <summary>
    /// Comparer against primary key Id
    /// </summary>
    public class ResidentIdComparer : IEqualityComparer<Resident>
    {
        public bool Equals(Resident x, Resident y) => Equals(x.Id, y.Id);
        public int GetHashCode(Resident obj) => obj.Id.GetHashCode();
    }
}

测试方法(位于单元测试项目/类中)

[TestMethod]
public void NoDuplicateNameExample()
{
    var residents = new List<Resident>
    {
        new() {Id = 1, Name = "Yelena", City = "Portland"},
        new() {Id = 2, Name = "Mary", City = "Portland"},
        new() {Id = 3, Name = "Lisa", City = "Portland"},
        new() {Id = 4, Name = "Jon", City = "Portland"},
        new() {Id = 5, Name = "Mary", City = "Salem"},
        new() {Id = 6, Name = "Bill", City = "Salem"},
        new() {Id = 7, Name = "Anne", City = "Salem"},
        new() {Id = 8, Name = "Jon", City = "Salem"}
    };

    var noDuplicateNames = residents.Distinct(new ResidentNameComparer());
    Assert.IsTrue(noDuplicateNames.Count() == 6);
}
[TestMethod]
public void NoDuplicateIdExample()
{
    var residents = new List<Resident>
    {
        new() {Id = 1, Name = "Yelena", City = "Portland"},
        new() {Id = 2, Name = "Mary", City = "Portland"},
        new() {Id = 1, Name = "Lisa", City = "Portland"},
        new() {Id = 1, Name = "Jon", City = "Portland"},
        new() {Id = 5, Name = "Mary", City = "Salem"},
        new() {Id = 1, Name = "Bill", City = "Salem"},
        new() {Id = 7, Name = "Anne", City = "Salem"},
        new() {Id = 1, Name = "Jon", City = "Salem"}
    };

    var noDuplicateIdentifiers = residents.Distinct(new ResidentIdComparer());
    Assert.IsTrue(noDuplicateIdentifiers.Count() == 4);

}
相关问题