Сортировка коллекции и вложенной коллекции одновременно - PullRequest
1 голос
/ 31 августа 2010

У меня есть IQueryable<Product>, который нужно отсортировать по Name. Каждый Product имеет IQueryable<Category>, который также должен быть отсортирован по Name. Мне трудно выразить это в Linq. Я мог бы пройтись по продуктам и отсортировать каждый список категорий, но это кажется грязным. Надеясь на ниндзя Линка, есть более разумное решение.

Мой Product класс выглядит так:

public class Product {
    public string Name { get; set; }
    public IQueryable<Category> Categories { get; set; }
}

Мой Category класс выглядит так:

public class Category { 
    public string Name { get; set; }
}

В настоящее время я делаю это:

 var myProducts = products.OrderBy(x => x.Name).Select(x => new Product { 
    Name = x.Name,
    Categories = x.Categories(y => y.Name)
});

Проблема в том, что при использовании чего-то вроде NHibernate это создает новые объекты Product, по существу отключая продукт от сеанса NH.

Ответы [ 4 ]

1 голос
/ 31 августа 2010

Вы не хотите изменять объект Product каким-либо образом, который может повлиять на постоянство, и вы не хотите создавать новые Product экземпляры.

Так что добавьте это в Product class:

public IOrderedEnumerable<Category> CategoriesOrderedByName
{
  get { return this.Categories.OrderBy(y => y.Name); }
}

И используйте product.CategoriesOrderedByName вместо этого, когда вам нужна отсортированная версия в вашем коде пользовательского интерфейса.использование вашего класса не предполагает, что объекты Category будут отсортированы каким-либо образом.При этом вы четко информируете потребителей своего класса, что ожидать, и что вы намереваетесь всегда возвращать их в отсортированном порядке.Вы также можете использовать IOrderedEnumerable<> в качестве возвращаемого типа, чтобы разрешить дальнейшую подсортировку с использованием ThenBy().

0 голосов
/ 31 августа 2010

Если вы хотите перечислить объекты Product в отсортированном порядке, а внутри каждого Product вы хотите Categories в отсортированном порядке, вы можете сделать что-то вроде этого.

var sorted = products
    .Select(
        p => new
        {
            Product = p,
            Categories = p.Categories.OrderBy(c => c.Name)
        }
    )
    .OrderBy(x => x.Product.Name);

Похоже, что это в основном то, что имеет Рональд , только без использования синтаксиса LINQ.

0 голосов
/ 31 августа 2010

Почему бы просто не отсортировать перечислимое на месте?

products = products.OrderBy(x => x.Name);
products.ToList().ForEach(x => x.Categories = x.Categories.OrderBy(y => y.Name));

Как уже говорили другие, это может плохо работать, если вы подключены.

0 голосов
/ 31 августа 2010

Может быть, это то, что вы хотите?Однако вы не получите список продуктов, каждый из которых имеет список категорий.Это невозможно с помощью LINQ, потому что вы не можете изменить коллекцию с помощью LINQ, вы можете только создать новую коллекцию из существующей (в моем примере p.Categories - это существующая коллекция, SortedCategories - новая).

from p in products
orderby p.Name
select new
{
    Product = p,
    SortedCategories = from c in p.Categories
                       orderby c.Name
                       select c
}

Вы говорите, что у вас есть IQueryable.Означает ли это, что вы запрашиваете у базы данных, используя этот оператор LINQ?Я не уверен, насколько хорошо это преобразуется в SQL (с точки зрения производительности).

...