如何加入 List<Class> 和 IEnumerable<Class>?

How join List<Class> with IEnumerable<Class>?

我有以下 classes.

  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<Course>,priceGroups 是 IEnumerable<PriceGroup>。正如您在课程 class 中看到的那样,一门课程有一个 List<PriceGroup>。我需要以某种方式将 IEnumerable<PriceGroup> 中的每个 PriceGroup 添加到 IEnumerable<Course> 中每个课程的列表中(如果它们在变量 CourseNumber 上匹配)。所以我最终会得到一个包含正确 List<PriceGroup>

的正确课程
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 做不到的事情。有谁知道实现我需要的方法吗?

//Assuming courseNumber is unique in Courses table
return Courses.Select( c=> { c.PriceGroup=priceGroup.Where(p=>p.CourseNumber==c.CourseNumber).ToList(); return c; });

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

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; }
}

当您 return 来自数据库的数据时,您应该避免使用 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; }
}

因此您需要所有(或部分)课程,每个课程及其所有(或部分)价格组。

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();