#c# #linq
Вопрос:
У меня проблема с объединением некоторых списков вместе, я думал, что это будет простое объединение LINQ, но я думаю, что это немного сложнее, и я хожу по кругу. У меня есть 3 таблицы ниже:
Таблица 1: Основной перечень продуктов
Продукт |
---|
ПРОД1 |
ПРОД2 |
ПРОД3 |
ПРОД4 |
Таблица 2: Продукт и соответствующая брошюра
Продукт | Листовка |
---|---|
ПРОД1 | Документ23 |
ПРОД2 | Документ18 |
ПРОД3 | Docu322 |
ПРОД4 | Документ121 |
Таблица 3: Продукт и соответствующие этикетки
Продукт | Этикетка |
---|---|
ПРОД1 | Lbl29 |
ПРОД2 | Lbl2 |
ПРОД3 | Lbl222 |
ПРОД5 | Lbl01 |
Конечный результат должен быть:-
Продукт | Листовка | Этикетка |
---|---|---|
ПРОД1 | Документ23 | Lbl29 |
ПРОД2 | Документ18 | Lbl2 |
ПРОД3 | Docu322 | Lbl222 |
ПРОД4 | Документ121 | |
ПРОД5 | Lbl01 |
Примечание: Некоторые продукты могут не иметь брошюры, а некоторые продукты могут не иметь этикетки. Кроме того, листовки и этикетки могут быть связаны с несколькими продуктами.
Вот запрос, который я пытался выполнить, он сводит все воедино, но есть много странных дубликатов строк.
PMatrix = (from a in AllProducts
join b in Leaflets on a.Product equals b.Product into b_grp
from b in b_grp.DefaultIfEmpty()
join c in Labels on a.Product equals c.Product into c_grp
from c in c_grp.DefaultIfEmpty()
select new ProductMatrixModel
{
Product = a.Product,
Leaflet = b == null ? "" : b.Leaflet,
Label = c == null ? "" : c.Label
}).ToBindableCollection();
Извините за уродливые растянутые столы, я не вижу, как установить ширину.
Комментарии:
1. Да, извините, я это и имел в виду, я обновлю.
2. «У некоторых продуктов не может быть листовки, а у некоторых листовок не может быть этикетки», — но вы соединяете обе таблицы с продуктом без дополнительного условия для листовок с этикетками.
3. А, я вижу последние новости. Спасибо, теперь я понимаю.
4. Есть ли эти данные в базе данных/вам нужно, чтобы ответ был переведен в SQL формы A ЛЕВОЕ СОЕДИНЕНИЕ B ЛЕВОЕ СОЕДИНЕНИЕ C?
5. Возможно, также стоит отметить, что в вашем основном списке продуктов отсутствует опечатка Prod5?
Ответ №1:
Я не смог протестировать приведенный ниже код, но если вам нравятся выражения LINQ, вы можете попробовать что-то подобное. Некоторое время назад я сделал нечто подобное.
AllProducts
.GroupJoin(Leaflets , l => l.Product, r => r.Product, (a, b) => new ProductMatrixModel { Product = a, Leaflet = b.FirstOrDefault() ?? string.Empty })
.GroupJoin(Labels, l => l.Product, r => r.Product, (a, b) => new ProductMatrixModel { Product = a.Product , Leaflet = a.Leaflet, Label = b.FirstOrDefault() ?? string.Empty })
.ToBindableCollection();
Приведенное выше выражение использует «FirstOrDefault», поэтому оно будет принимать первый результат из возможных совпадений соединений. Если вам требуются все совпадения соединения, то вам нужно обновить свое модальное свойство до списка и соответственно работать с данными.
Примером того, о чем я упоминал выше, может быть:
- Измените модальный на что-то вроде этого
public class ProductMatrixModel { public ProductMatrixModel() { this.Labels = new List<string>(); this.Leaflets = new List<string>(); } public string Product { get; set; } public List<string> Labels { get; set; } public List<string> Leaflets { get; set; } }
- Затем используйте выражение LINQ следующим образом:
AllProducts .GroupJoin(Leaflets , l => l.Product, r => r.Product, (a, b) => new ProductMatrixModel { Product = a, Leaflets = b }) .GroupJoin(Labels, l => l.Product, r => r.Product, (a, b) => new ProductMatrixModel { Product = a.Product , Leaflets = a.Leaflets, Labels = b }) .ToBindableCollection();
Приведенный выше запрос LINQ должен затем предоставить вам IEnumerable с каждым объектом Productmatrix Model, содержащим строку продукта, со связанным списком этикеток и листовок.
Вы можете зациклить каждый объект Productmatrix Model и делать с ним все, что вам нравится, связанные с ним данные. Я предполагаю, что вы хотели бы показать его в строке, разделенной запятыми.
Вот пример того, как отобразить список строк в виде строки, разделенной запятыми.
string.Join(",", Leaflets.Select(s => s));
Комментарии:
1. Спасибо за ответ, но я получаю исключение со второй группой. Ошибка CS0411 Аргументы типа для метода ‘Перечислимы. Объединение групп<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter, TInner, TKey, TResult><TOuter>, IEnumerable<TOuter><TInner>, Функция<TInner><TOuter, TKey>, Функция<TOuter, TKey><TInner, TKey>, Функция<TInner, TKey><TOuter, IEnumerable<TInner>, TResult<TInner>>) не может быть выведено из использования. Попробуйте явно указать аргументы типа.
2. Что говорится в исключении?
3. А, понятно. Это связано с динамическими объектами. Я быстро обновлю информацию
4. Я обновил его, сделав его конкретным объектом для каждого соединения, а не динамическим, что должно решить проблему.
5. «Последовательность содержит больше, чем элемент» исключение для первой группы, присоединенной к новой модели ProductMatrixModel { … }