Как объединить список <Class>с IEnumerable <Class>? - PullRequest
1 голос
/ 04 мая 2020

У меня есть следующие классы.

  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<Course> и PriceGroups IEnumerable<PriceGroup>. Как вы можете видеть в классе курса, курс имеет List<PriceGroup>. Мне нужно как-то добавить каждую группу PriceGroup из IEnumerable<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. Кто-нибудь знает способ добиться того, что мне нужно?

Ответы [ 3 ]

1 голос
/ 05 мая 2020

Таким образом, вам нужны все (или некоторые) курсы, каждый курс со всеми (или некоторыми) из его PriceGroups.

Существует прямое отношение один ко многим между курсами и PriceGroups: каждый курс имеет ноль или более PriceGroups, каждая PriceGroup принадлежит только одному Курсу, а именно Курсу, на который ссылается внешний ключ CourseNumber.

Вы правы, когда вы хотите, чтобы элементы с их подэлементами использовали 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();
0 голосов
/ 04 мая 2020

Я сделал практический пример, очевидно, вы должны заменить поддельные методы репозиториевыми:

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; }
}
0 голосов
/ 04 мая 2020
//Assuming courseNumber is unique in Courses table
return Courses.Select( c=> { c.PriceGroup=priceGroup.Where(p=>p.CourseNumber==c.CourseNumber).ToList(); return c; });
...