【问题标题】:How join List<Class> with IEnumerable<Class>?如何加入 List<Class> 和 IEnumerable<Class>?
【发布时间】:2020-05-04 14:34:51
【问题描述】:

我有以下课程。

  public class Course 
    {
        public string CourseNumber { get; set; }
        public List<PriceGroup> PriceGroups { get; set; }
    }


   public class PriceGroup
    {
        public int Id { get; set; }
        public string CourseNumber { get; set; }
    }

我有一个从数据库中获取数据的服务。 Courses 是 IEnumerable&lt;Course&gt;,priceGroups 是 IEnumerable&lt;PriceGroup&gt;。正如您在 Course 类中所见,课程具有 List&lt;PriceGroup&gt;。如果它们与变量CourseNumber 匹配,我需要以某种方式将IEnumerable&lt;PriceGroup&gt; 中的每个PriceGroup 添加到IEnumerable&lt;Course&gt; 中每门课程的列表中。所以我最终会得到一个正确的课程,其中包含正确的List&lt;PriceGroup&gt;'s

public async Task<IEnumerable<Course>> GetAllAsync()
        {
            //courses is an IEnumerable<Course>
            var courses = await _courseRepository.GetAllAsync();

            //priceGroups is an IEnumerable<PriceGroup>
            var priceGroups = await _coursePriceGroupRepository.GetAllAsync();     

            courses.GroupJoin(priceGroups, c => c.PriceGroups.Select(i => i.CourseNumber), pg => pg.CourseNumber, (c, pg) => new
            {

            });    
            return await courses;
        }

为此,我尝试进行 GroupJoin,但没有成功。我还没有完成尝试,因为我完全被困在了精神上。也许我正在尝试使用 GroupJoin 做一些不可能的事情。有谁知道实现我需要的方法?

【问题讨论】:

  • 如果底层数据层是实体框架,你为什么不IncludePriceGroups

标签: linq lambda poco


【解决方案1】:

所以你想要所有(或部分)课程,每门课程都有其所有(或部分)PriceGroups。

Courses 和 PriceGroups 之间存在直接的一对多关系:每个 Course 都有零个或多个 PriceGroups,每个 PriceGroup 只属于一个 Course,即外键 CourseNumber 所指的 Course。

你是对的,只要你想要项目及其子项目,你就可以使用 GroupJoin。

public async Task<IEnumerable<Course>> GetAllAsync()
{
    IEnumerable<Course> courses = await _courseRepository.GetAllAsync();
    IEnumerable<PriceGroup> priceGroups = await _coursePriceGroupRepository.GetAllAsync();     

    var queryCoursesWithPriceGroups = courses.GroupJoin( // GroupJoin Courses
        priceGroups,                                     // with PriceGroups
        course => course.CourseNumber,                   // from every Course take primary key
        priceGroup => priceGroup.CourseNumber,           // from every PriceGroup take foreign key
        (course, priceGroupsOfThisCourse) => new        // from every Course with
        {                                               // its priceGroups make one new
             // Select the Course properties you plan to use:
             Id = course.Id,
             Name = course.Name,
             StartDate = course.StartDate,
             ...

             PriceGroups = priceGroupsOfThisCourse.Select(priceGroup => new
             {
                  // Select only the PriceGroup properties that you plan to use
                  Id = priceGroup.Id,
                  Name = priceGroup.Name,
                  ...

                  // not needed, you know the value:
                  // CourseId = priceGroup.CourseId
             })
             .ToList(),
       });
       // Note: this is a query. It is not executed yet!

       return await queryCoursesWithPriceGroups.ToListAsync();

【讨论】:

  • 很棒的反应。非常感谢。你对每一步都发表评论真的很有帮助。在此之前,整个事情让我感到困惑。干得好!
【解决方案2】:
//Assuming courseNumber is unique in Courses table
return Courses.Select( c=> { c.PriceGroup=priceGroup.Where(p=>p.CourseNumber==c.CourseNumber).ToList(); return c; });

【讨论】:

    【解决方案3】:

    我做了一个实际的例子,显然你应该用存储库的方法代替假方法:

    class Program
    {
        static async void Main(string[] args)
        {
            var courses = GetAllAsync().Result;
        }
    
        private static async Task<IEnumerable<Course>> GetAllAsync()
        {
            //courses is an IEnumerable<Course>
            var courses = await GetCoursesAsync();
    
            //priceGroups is an IEnumerable<PriceGroup>
            var priceGroups = await GetPriceGroups();
    
            foreach (var course in courses)
            {
                foreach (var priceGroup in priceGroups.Where(x => x.CourseNumber == course.CourseNumber))
                {
                    course.PriceGroups.Add(priceGroup);
                }
            }
    
            return courses;
        }
    
        private static async Task<IEnumerable<Course>> GetCoursesAsync()
        {
            return await Task.FromResult<IEnumerable<Course>>(
                new List<Course>() {
                    new Course{
                        CourseNumber = "PIZZA1",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA2",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA3",
                        PriceGroups = new List<PriceGroup>()
                    },
                }
            );
        }
    
        private static async Task<IEnumerable<PriceGroup>> GetPriceGroups()
        {
            return await Task.FromResult<IEnumerable<PriceGroup>>(
                new List<PriceGroup>() {
                    new PriceGroup{
                        Id = 1,
                        CourseNumber = "PIZZA1"
                    },
                    new PriceGroup{
                        Id = 2,
                        CourseNumber = "PIZZA2"
                    },
                    new PriceGroup{
                        Id = 3,
                        CourseNumber = "PIZZA3"
                    }
                }
            );
        }
    }
    
    public class Course
    {
        public string CourseNumber { get; set; }
        public List<PriceGroup> PriceGroups { get; set; }
    }
    
    public class PriceGroup
    {
        public int Id { get; set; }
        public string CourseNumber { get; set; }
    }
    

    从数据库返回数据时应避免使用 IEnumerable,否则可能会导致意外行为。我建议你采用这种方法:

    class Program
    {
        static void Main(string[] args)
        {
            var courses = GetAllAsync().Result;
        }
    
        private static async Task<List<Course>> GetAllAsync()
        {
            var courses = await GetCoursesAsync();
    
            var priceGroups = await GetPriceGroups();
    
            courses.ForEach(x => { x.PriceGroups.AddRange(priceGroups.Where(y => y.CourseNumber == x.CourseNumber)); });
    
            return courses;
        }
    
        private static async Task<List<Course>> GetCoursesAsync()
        {
            return await Task.FromResult(
                new List<Course>() {
                    new Course{
                        CourseNumber = "PIZZA1",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA2",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA3",
                        PriceGroups = new List<PriceGroup>()
                    },
                }
            );
        }
    
        private static async Task<List<PriceGroup>> GetPriceGroups()
        {
            return await Task.FromResult(
                new List<PriceGroup>() {
                    new PriceGroup{
                        Id = 1,
                        CourseNumber = "PIZZA1"
                    },
                    new PriceGroup{
                        Id = 2,
                        CourseNumber = "PIZZA2"
                    },
                    new PriceGroup{
                        Id = 3,
                        CourseNumber = "PIZZA3"
                    }
                }
            );
        }
    }
    
    public class Course
    {
        public string CourseNumber { get; set; }
        public List<PriceGroup> PriceGroups { get; set; }
    }
    
    public class PriceGroup
    {
        public int Id { get; set; }
        public string CourseNumber { get; set; }
    }
    

    我也使用 GroupJoin 制作了一个版本:

    class Program
    {
        static void Main(string[] args)
        {
            var courses = GetAllAsync().Result;
        }
    
        private static async Task<List<Course>> GetAllAsync()
        {
            var courses = await GetCoursesAsync();
    
            var priceGroups = await GetPriceGroups();
    
            var groupedData = courses.GroupJoin(priceGroups,
                    course => course.CourseNumber,
                    priceGroup => priceGroup.CourseNumber,
                    (course, priceGroupsCollection) =>
                    new
                    {
                        CourseNumber = course.CourseNumber,
                        PriceGroups = priceGroupsCollection.ToList()
                    });
    
            courses.ForEach(x => { x.PriceGroups = groupedData.FirstOrDefault(y => y.CourseNumber == x.CourseNumber)?.PriceGroups ?? new List<PriceGroup>(); });
    
            return courses;
        }
    
        private static async Task<List<Course>> GetCoursesAsync()
        {
            return await Task.FromResult(
                new List<Course>() {
                    new Course{
                        CourseNumber = "PIZZA1",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA2",
                        PriceGroups = new List<PriceGroup>()
                    },
                    new Course{
                        CourseNumber = "PIZZA3",
                        PriceGroups = new List<PriceGroup>()
                    },
                }
            );
        }
    
        private static async Task<List<PriceGroup>> GetPriceGroups()
        {
            return await Task.FromResult(
                new List<PriceGroup>() {
                    new PriceGroup{
                        Id = 1,
                        CourseNumber = "PIZZA1"
                    },
                    new PriceGroup{
                        Id = 2,
                        CourseNumber = "PIZZA2"
                    },
                    new PriceGroup{
                        Id = 3,
                        CourseNumber = "PIZZA3"
                    },
                    new PriceGroup{
                        Id = 4,
                        CourseNumber = "PIZZA1"
                    }
                }
            );
        }
    }
    
    public class Course
    {
        public string CourseNumber { get; set; }
        public List<PriceGroup> PriceGroups { get; set; }
    }
    
    public class PriceGroup
    {
        public int Id { get; set; }
        public string CourseNumber { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多