2016-10-17 87 views
0

好吧,我写了下面LINQ to Entities查询(足够接近下方显示我的C#查询)LINQ到过滤嵌套列表

var itemss = filteredstudents 
.Where(x => x.SubjectTypes.Any(y => y.SubjectItem.Any(z => z.Name == value1))).ToList(); 

还是有点问题,因为当SubjectItem类型有两个元素,其中一人用value1匹配。它仍然返回两者。它应该只返回匹配的记录。我知道问题是与任何但不知道Any取代什么?

foreach (StudentDTO student in filteredstudents) 
{ 
    bool valid = true; 
    foreach (SubjectTypes subjectType in student.SubjectTypes) 
    { 
     string value1 = subjectType.SubjectItem.Select(x => x.value1).First(); 
     Guid StId = _context.Items.Where(x => x.Name == value1).FirstOrDefault(); 

     if (StId != null) 
      valid = true; 
     else 
     { 
      valid = false; 
      _log("create log"); 
     } 
    } 
    if (valid) 
     filteredstudentsWithUnits.Add(student); 
} 

采样输入

{"Name":"ABC", 
"Age":12, 
,"SubjectTypes": 
[ 
{"Id":"1","Description":""Description","SubjectItem":[{"Id":"1","Marks":12,"Name":"aaa"}]}, 
{"Id":"1","Description":""Description","SubjectItem":[{"Id":"1","Marks":12,"Name":"aaa"}]}, 
{"Id":"1","Description":""Description","SubjectItem":[{"Id":"1","Marks":12,"Name":"bbb"}]} 
] 
} 

期望输出

{"Name":"ABC", 
"Age":12, 
,"SubjectTypes": 
[ 
{"Id":"1","Description":""Description","SubjectItem":[{"Id":"1","Marks":12,"Name":"aaa"}]}, 
{"Id":"1","Description":""Description","SubjectItem":[{"Id":"1","Marks":12,"Name":"aaa"}]}, 

] 
} 
+0

请分享'SubjectTypes'和'SubjectItem' – Jacky

+0

之间的关系也将是有益的,如果你发布的示例数据和预期输出 –

+0

你能解释一下在多个项目的情况下会发生什么?它应该只会返回,如果有一个项目,它匹配,如果是的话,那么你这样做的问题是什么(似乎没有比你在这里的其他东西更难) – Chris

回答

0

看看下面的代码测试数据它过滤器嵌套列表集合。有两种解决方案,第一种是简单的Linq查询应用程序,另一种是扁平化和重新分组,可以用于相对复杂的场景,需要更多的数据控制。

测试数据:

创建具有列表为嵌套集合需要被过滤的一个StudentDTO

public class StudentDTO 
{ 
    public string SName { get; set; } 

    public int Age { get; set; } 

    public List<Subject> Subjects { get; set; } 

    public static IEnumerable<StudentDTO> FetchList() 
    { 
     List<StudentDTO> testList = new List<StudentDTO>(); 

     testList.Add(new StudentDTO { SName = "M", Age = 12, Subjects = new List<Subject>() { new Subject {Id = 1, Marks = 100, Name = "AAA"} , 
                          new Subject {Id = 1, Marks = 98, Name = "AAA"}, 
                          new Subject {Id = 1, Marks = 100, Name = "BBB"}     
                          }}); 

     return testList; 
    } 
} 

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

    public int Marks{ get; set; } 

    public string Name { get; set; } 

} 

解决方案:1(简单LINQ查询应用程序)

var studentListFiltered = 
studentList.Select(x => 
        new StudentDTO { 
            SName = x.SName, 
            Age = x.Age, 
            Subjects = x.Subjects 
               .Where(n => n.Name == "AAA").ToList() 
            }); 

解决方案:2(压扁和重新分组)

- 创建包含StudentDTO列表测试数据

var studentList = StudentDTO.FetchList(); 

- 展平列表,以便容易地过滤数据

var studentListFlattened = 
    studentList.SelectMany(x => x.Subjects.Select(y => new {x.SName,x.Age,y.Id,y.Marks,y.Name})); 

- 过滤数据,使用父实体列对其进行分组并创建原始嵌套结构

var studentListFiltered = 
    studentListFlattened.Where(x => x.Name == "AAA") 
         .GroupBy(x => new { SName = x.SName, Age = x.Age }) 
         .ToDictionary(x => x.Key, x => x.Select(n => new Subject {Id = n.Id,Marks = n.Marks,Name = n.Name}).ToList()) 
         .Select(x => new StudentDTO{ SName = x.Key.SName, Age = x.Key.Age, Subjects = x.Value}); 

studentListFiltered包含最终结果,带有过滤的嵌套列表。可以使用类似的策略/代码按照用例过滤任何级别的嵌套列表

0

您可以先使用.Where过滤列表,然后使用.Select来投影到仅包含所需数据的新集合。像下面的内容可能工作:

var itemss = filteredstudents 
    .Where(s => s.SubjectTypes.Any(st => st.SubjectItem.Any(si => si.Name == value1))) 
    .Select(s => new StudentDTO 
    { 
     Name = s.Name, 
     Age = s.Age, 
     SubjectTypes = s.SubjectTypes.Where(st => st.SubjectItem.Any(si => si.Name == value1)) 
      .Select(st => new SubjectType 
      { 
       Id = st.Id, 
       Description = st.Description, 
       SubjectItem = st.SubjectItem.Where(si => si.Name == value1).ToList() 
      }).ToList() 
    }) 
    .ToList(); 
0

这将解决您的问题,但也有可能做的更好的办法,我也省略一样,你将需要添加的ID和标记的一些属性。

var items = filteredstudents.Select(s => new StudentDTO 
{ 
    Name = s.Name, 
    SubjectTypes = s.SubjectTypes.Select(st => new SubjectType 
    { 
     Description = st.Description, 
     SubjectItems = st.SubjectItems.Where(si => si.Name == "AAA").ToList() 
    }).Where(x => x.SubjectItems.Count > 0).ToList() 
});