【问题标题】:Efficiently Filtering One DataTable matching multiple columns of another DataTable in C#在 C# 中有效地过滤一个匹配另一个 DataTable 的多个列的 DataTable
【发布时间】:2018-03-28 04:22:24
【问题描述】:

我有两个 DataTable,我有一个过滤匹配记录的功能。以下是我的功能:

public static DataTable FilterCandidates(DataTable FullCandidateData, DataTable RequiredCandidateIDs)
{
    DataTable ReqCandidateData = new DataTable();
    try
    {
        var MacthingIDs = FullCandidateData.AsEnumerable().Select(r => r.Field<string>("Candidate_ID")).Intersect(RequiredCandidateIDs.AsEnumerable().Select(r => r.Field<string>("Candidate_ID")));

        ReqCandidateData = (from row in FullCandidateData.AsEnumerable()
                            join Candidate_ID in MacthingIDs
                            on row.Field<string>("Candidate_ID") equals Candidate_ID
                            select row).CopyToDataTable();
        return ReqCandidateData;
    }
    catch (Exception ex)
    {
        ReqCandidateData = FullCandidateData.Clone();
        return ReqCandidateData;
    }
}

有没有其他有效的方法可以做到这一点,不知何故我不喜欢假设异常等同于没有匹配的记录。我也可以通过查找长度来做到这一点,但它会大大增加循环数,我的第一个 DataTable 中有大约 90,000 个候选者,并且还在不断增长。

另外,如果我有多列比较,例如 Candidate_IDJob_ID

,请告诉我该怎么做

【问题讨论】:

    标签: c# asp.net performance linq datatable


    【解决方案1】:

    您可以使用单个联接来实现您的目的。下面的第一个函数仅匹配 Candidate_ID,第二个函数同时匹配 Candidate 和 job id。参考第三种方法从“FullCandidateData”中获取所有与“RequiredCandidateIDs”不匹配的行

    public static System.Data.DataTable FilterCandidates(System.Data.DataTable FullCandidateData, System.Data.DataTable RequiredCandidateIDs)
    {
        System.Data.DataTable reqCandidateData = new System.Data.DataTable();
        try
        {
            var reqCandidateDt = (from candidateRow in FullCandidateData.AsEnumerable()
                                  join reqCandidateRow in RequiredCandidateIDs.AsEnumerable()
                                  on candidateRow["Candidate_ID"].ToString() equals reqCandidateRow["Candidate_ID"].ToString()
                                  select candidateRow);
    
            if (reqCandidateDt.Count() > 0)
            {
                reqCandidateData = reqCandidateDt.CopyToDataTable();
            }
        }
        catch (Exception ex)
        {
    
        }
        return reqCandidateData;
    }
    
    
    
    
    public static System.Data.DataTable FilterCandidates(System.Data.DataTable FullCandidateData, System.Data.DataTable RequiredCandidateIDs)
    {
        System.Data.DataTable reqCandidateData = new System.Data.DataTable();
        try
        {
            var reqCandidateDt = (from candidateRow in FullCandidateData.AsEnumerable()
                                  join reqCandidateRow in RequiredCandidateIDs.AsEnumerable()
                                  on
                                  new { CandidateId = candidateRow["Candidate_ID"].ToString(), Job_Id = candidateRow["Job_ID"].ToString() }
                                  equals
                                  new { CandidateId = reqCandidateRow["Candidate_ID"].ToString(), Job_Id = reqCandidateRow["Job_Id"].ToString() }
                                  select candidateRow);
    
            if (reqCandidateDt.Count() > 0)
            {
                reqCandidateData = reqCandidateDt.CopyToDataTable();
            }
        }
        catch (Exception ex)
        {
    
        }
        return reqCandidateData;
    }
    
    public static System.Data.DataTable FilterCandidates(System.Data.DataTable FullCandidateData, System.Data.DataTable RequiredCandidateIDs)
    {
        System.Data.DataTable reqCandidateData = new System.Data.DataTable();
        try
        {
            var reqCandIds = RequiredCandidateIDs.AsEnumerable().Select(reqCandidateRow => reqCandidateRow["Candidate_ID"].ToString());
            var reqCandidateDt = (from candidateRow in FullCandidateData.AsEnumerable()
                                  where !reqCandIds.Contains(candidateRow["Candidate_ID"].ToString())
                                  select candidateRow);
    
            if (reqCandidateDt.Count() > 0)
            {
                reqCandidateData = reqCandidateDt.CopyToDataTable();
            }
        }
        catch (Exception ex)
        {
    
        }
        return reqCandidateData;
    }
    

    【讨论】:

    • 嗨,非常感谢,我想当没有匹配的记录时, .CopyToDataTable();抛出异常。
    • 你有大约 6k 的声誉,但你的代码格式是一团糟。
    • 嗨@AksheyBhat,如果我想从“FullCandidateData”中获取与“RequiredCandidateIDs”不匹配的所有行,我该怎么办,我看到了很多线程,但它们都使用字段类型,我想在不使用字段类型的情况下做到这一点。
    • @PrasanthKumarVinakota 参考第三种方法,在不使用字段类型的情况下从“FullCandidateData”中获取所有与“RequiredCandidateIDs”不匹配的行
    【解决方案2】:

    我的第一个数据表中有大约 90,000 名候选人,并且还在不断增长。

    关于这一点,您可能需要开始设计/考虑负载。

    我建议:

    1. 在数据进入数据表之前根据日期过滤数据 - 为用户提供从存档表中搜索数据的便利
    2. 是的,选择正确的多键过滤数据。在这种情况下,过滤器顺序也很重要。
    3. 保持将数据计数控制在控制范围内的目标,否则您将出现性能问题
    4. 对于大数据集的过滤,可以考虑放到数据库端,效率更高,速度更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-27
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多