根据涉及其他行的条件,使用LINQ to SQL过滤集合

时间:2013-01-08 21:47:59

标签: c#-4.0 linq-to-sql c#-3.0

我正在使用LINQ to SQL获取数据集。我需要过滤这个数据集:

如果存在具有null SourceName的字段,并且此字段的至少一个其他记录具有非null SourceName,则应将其删除。

如果它是该“字段”的唯一行,则它应保留在列表中。

以下是一个示例数据:数据由3列组成:'Field','SourceName'和'Rate'

Field | SourceName |  Rate 
 10   |    s1      |   9   
 10   |    null    |   null
 11   |    null    |   null
 11   |    s2      |   5
 11   |    s3      |   4
 12   |    null    |   null
 13   |    null    |   null
 13   |    s4      |   7
 13   |    s5      |   8
  8   |    s6      |   2
  9   |    s7      |   23
  9   |    s8      |   9
  9   |    s9      |   3   

输出应如下所示:

Field | SourceName | Rate 
 10   |  s1        |  9   
 11   |  s2        |  5
 11   |  s3        |  4
 12   |  null      |  null    //  <- (remains since there's only 
 13   |  s4        |  7       //      1 record for this 'Field')
 13   |  s5        |  8
  8   |  null      |  null
  9   |  s8        |  9
  9   |  s9        |  3     

如何过滤它?

2 个答案:

答案 0 :(得分:1)

您尝试实现的目标并非无足轻重,只能通过.Where()子句来解决。您的过滤条件取决于需要分组的条件,因此您必须.GroupBy(),然后使用.SelectMany()展平该集合集合。

以下代码使用LINQ to Objects满足您的预期输出,我没有看到任何LINQ to SQL无法将其转换为SQL的原因,没有尝试过那么难。

        //Group by the 'Field' field.
yourData.GroupBy(x => x.Field)

        //Project the grouping to add a new 'IsUnique' field
        .Select(g => new { 
                        SourceAndRate = g,
                        IsUnique = g.Count() == 1,
        })

        //Flatten the collection using original items, plus IsUnique
        .SelectMany(t => t.SourceAndRate, (t, i) => new {
                        Field = t.SourceAndRate.Key,
                        SourceName = i.SourceName, 
                        Rate = i.Rate,
                        IsUnique = t.IsUnique
        })

        //Now we can do the business here; filter nulls except unique
        .Where(x => x.SourceName != null || x.IsUnique);

答案 1 :(得分:0)

使用Linq内置的'Where'子句和lambda continuation:

使用lambda和一个简单的POCO类将数据存储在像你这样的列表中的简单静态示例:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Simple
{
    class Program
    {
        class Data
        {
            public string Field { get; set; }
            public string SourceName { get; set; }
            public string Rate { get; set; }
        }

        static List<Data> Create()
        {
            return new List<Data>
                {
                    new Data {Field = "10", SourceName = null, Rate = null},
                    new Data {Field = "11", SourceName = null, Rate = null},
                    new Data {Field = "11", SourceName = "s2", Rate = "5"}
                };
        }

        static void Main(string[] args)
        {
            var ls = Create();

            Console.WriteLine("Show me my whole list: \n\n");

            // write out everything
            ls.ForEach(x => Console.WriteLine(x.Field + "\t" + x.SourceName + "\t" + x.Rate + "\n"));


            Console.WriteLine("Show me only non nulls: \n\n");

            // exclude some things
            ls.Where(l => l.SourceName != null)
                .ToList()
                .ForEach(x => Console.WriteLine(x.Field + "\t" + x.SourceName + "\t" + x.Rate + "\n"));

            Console.ReadLine();
        }
    }
}