2009-02-25 5 views
2

Я хочу, чтобы написать элегантный запрос Linq для обработки следующего объекта ОБРАЗЦА модели:Linq запрос с агрегатами

class Category 
    { 
     public string Name { get; set; }   
     public IList<Product> Products { get; set;}   
    } 

    class Product 
    { 
     public string Title { get; set; } 
     public IList<Photo> Photos { get; set; } 
    } 

    class Photo 
    { 
     public int Id { get; set; } 
    } 

я построил следующий запрос, чтобы получить фото Id:

var query = from category in Factory.GetCategories() 
       where category.Name == "Cameras" 
       select (from product in category.Products 
         where product.Title == "Sony" 
         select (from photo in product.Photos 
           select photo.Id) 
           ); 

    var v = query.ToList(); 

На момент запроса не проецировать правильно я должен добавить FirstOrDefault() для каждого из подкомитетов Selects !:

var query = from category in Factory.GetCategories() 
       where category.Name == "Cameras" 
       select (from product in category.Products 
         where product.Title == "Sony" 
         select (from photo in product.Photos 
           select photo.Id).FirstOrDefault() 
           ).FirstOrDefault(); 

var v = query.ToList(); 

Есть ли лучший способ сделать это? Игнорируя тот факт, что мы не имеем дело с базой данных и ПК/FK, не играют.

Я действительно хочу, чтобы не писать большой цикл, когда я мог бы сделать то же самое в запросе Linq:

foreach (var category in Factory.GetCategories()) 
      { 
       if (category.Name == "Camera") 
       { 
        foreach (var product in category.Products) 
        { 
         if (product.Title == "Sony") 
         { 
          foreach (var photo in product.Photos) 
          { 
           //get data 
           int id = photo.Id; 
          } 
         } 
        } 
       }     
      } 

Фактическая реализация является более сложной, чем это простой объектной модели. Я хочу получить основную идею из этого простого примера, поэтому я применил его к моей реальной объектной модели.

Cheers!

ответ

5

Вы просто хотите сплющенные идентификаторы?

 var query = from category in Factory.GetCategories() 
        where category.Name == "Cameras" 
        from product in category.Products 
        where product.Title == "Sony" 
        from photo in product.Photos 
        select photo.Id; 
+0

Cheers Marc, я думаю, вы и Джон предоставили тот же ответ :). Гораздо больше elgant, чем я первоначально начал с. – 2009-02-25 15:25:05

2

Ну да, вы должны добавить FirstOrDefault, потому что нет такого понятия, как «идентификатор фотографии». На камеру есть потенциально много фотографий - чего вы хотите?

Если вы заботитесь только о первой фотографии, это хорошо - хотя несколько «из» положения сделает вашу жизнь проще:

var query = from category in Factory.GetCategories() 
      where category.Name == "Cameras" 
      from product in category.Products 
      where product.Title == "Sony" 
      select product.Photos.Select(photo => photo.Id) 
           .FirstOrDefault(); 

Обратите внимание, что это будет возвращать 0 для продукта без каких-либо фотографий. Это то, что вы хотите?

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

EDIT: Если вы хотите, только самый первый идентификатор любой Sony камеры, а затем использовать:

var query = from category in Factory.GetCategories() 
      where category.Name == "Cameras" 
      from product in category.Products 
      where product.Title == "Sony" 
      from photo in product.Photos 
      select photo.Id; 
var firstId = query.FirstOrDefault(); 
0
 var ids = from category in Factory.Categories 
        where category.Name == "Cameras" 
        from product in category.Products 
        where product.Title == "Sony" 
        from photo in product.Photos 
        select photo.Id; 

Возвращает все идентификаторы фотографий, перечислимое пуст, когда нет фотографий. Если вы хотите первый, или по умолчанию 0:

var result = ids.FirstOrDefault(); 
1

Тот же ответ, как и все остальные, но с расширением метод вызывает вместо понимания запроса. SelectMany позволяет «распаковать» дочернюю коллекцию и продолжить запрос на этом уровне.

var query = Factory.GetCategories() 
    .Where(category => category.Name == "Cameras") 
    .SelectMany(category => category.Products) 
    .Where(product => product.Title == "Sony") 
    .SelectMany(product => product.Photos) 
    .Select(photo => photo.Id); 
Смежные вопросы