【问题标题】:Linq join with record of second tableLinq join 与第二个表的记录
【发布时间】:2021-03-23 02:14:42
【问题描述】:

我在 SO 上看过很多类似的问题,但似乎不是那么直截了当。 问题是,他们中的大多数都在处理IEnumerable,在我的情况下,我有两个IQueryable dbsets。

情况和here的问题有些相似。

Student
id     Name 
1      a1
2      b1
3      c1

Images
id   Image         StudentId      Status      ModifiedOn
1    1.jpg            1           Active      2021-03-12 02:02:32.580
2    2.jpg            1           Deleted     2021-03-12 02:01:32.580
3    3.jpg            2           Deleted     2021-03-12 02:02:32.580
4    4.jpg            2           Deleted     2021-03-12 02:01:32.580

Result 应该是

id  Name Image
1   a1   1.jpg
2   b1   3.jpg
3   c1   NULL 

我可以用 TSQL 和嵌套的 WITH qqueries 做到这一点,其中一个选择 Status = Active,另一个选择 Status != Active,然后合并这两个并选择 TOP 1。

但由于要求是编写等效的 LINQ,我从以下查询开始,因为我不知道在 Status = Active 上合并 CASE WHEN 的好方法。

        var aquery = context.Images;
        var lquery = context.Students;
        var result = from l in lquery
                     join a in aquery on l.Id equals a.StudentId into aGroup
                     from a in aGroup.OrderByDescending(m => m.ModifiedOn).Take(1)
                     select new {
                         l.id,
                         a.StudentId,
                         a.Status
                     };

这失败了dbsets 不是 IEnumerable。知道如何获得正确的结果吗?

【问题讨论】:

  • 那是因为IQuerable 使用数据库级别的所有过滤器执行 sql 查询。看这里:Returning IEnumerable<T> vs. IQueryable<T>
  • 正确,但我不知道如何使它与 dbset 一起工作。知道我的查询中有什么不那么 IQueryable 吗?

标签: c# entity-framework linq


【解决方案1】:

这个查询应该可以工作:

var query =
    from s in context.Students
    from i in context.Images
        .Where(i => i.StudentId = s.Id)
        .OrderBy(i => i.Status == "Active" ? 0 : 1)
        .ThenByDescending(i => i.ModifiedOn)
        .Take(1)
        .DefaultIfEmpty()
    select new 
    {
        s.Id,
        s.Name,
        i.Image
    };

【讨论】:

    【解决方案2】:
     IQueryable<Image> images = context.Images.AsQueryable();
     IQueryable<Student> students = context.Students;
    
                  
     var result =  (from st in students
                     select new
                        {
                            Id = st.Id,
                            Name = st.Name,
                            ImageName = images
                                .OrderBy(x => x.ModifiedAt)
                                .Where(x => x.Status)
                                .Where(i=> i.StudentId == st.Id)
                                .Select(x=> x.ImageName)
                                .FirstOrDefault()
                        })
                        .ToList();
    

    但最简单的选择是在 Student 类中为图像定义导航字段:

    public class Student{
    
       List<Image> Images {get; private set;}
    }
    

    然后:

     context.Students
             .Select(st=> new
                    {
                      Id = st.Id,
                      Name = st.Name,
                      ImageName = st.Images
                                    .OrderBy(x => x.ModifiedAt)
                                    .Where(x => x.Status)
                                    .Where(i=> i.StudentId == st.Id)
                                    .Select(x=> x.ImageName)
                                    .FirstOrDefault()
                     })
                     .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 1970-01-01
      • 2020-08-13
      • 2012-07-30
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      相关资源
      最近更新 更多