Linq присоединиться к запросу - PullRequest
1 голос
/ 14 ноября 2010

Например, БД с 2 таблицами

Book [BookId (int), Title (nvarchar), ShowInWebshop (bit)] and 
InventoryDetail [InventoryDetailId (int), BookId (int), Quantity (int)]

Выполнить: SELECT * FROM Books LEFT JOIN InventoryDetails ON books.BookId = InventoryDetails.BookId

В выходных данных отображаются все столбцы Книги и связанные столбцы InventoryDetails (включая столбец InventoryDetails.BookId) ..soпока все хорошо ... Пытаясь преобразовать этот запрос в Linq (используя LinqPad, сравнивая несколько примеров, здравый смысл и т. д.), я составил следующий общий список (потому что я хотел представить список)

private List<Book> Books(int count){
    var books = webshopDB.Books
        .Join<Book, InventoryDetail, int, Book>( webshopDB.InventoryDetails, 
            b => b.BookId, 
            i => i.BookId,
            (b, i) => b )
        .Where(b => b.ShowInWebshop == true)
        .Take(count)
        .ToList();
    return books
}

Этот модуль возвращает список книг!Не то, что я ожидал, хотя!Он возвращает только данные книги, такие как Title и ShowOnSite, а НЕ детали из таблицы InventoryDetail: Количество

Что я забыл?

Ответы [ 4 ]

1 голос
/ 16 ноября 2010

Результат, как это работает до сих пор ...

public ActionResult Index()
{                
    // This return a list of tuples {(WebshopDB.Models.Book, WebshopDB.Models.InventoryDetail)}
    // Each tuple containing two items: 
    // > Item1 {WebshopDB.Models.Book}
    // > Item2 {WebshopDB.Models.InventoryDetail}
    var tuple_books = ListOfTuples_BookInventoryDetail(5);
    ...
    // next step(s)
    // add a ViewModel viewmodel
    // ...
    return (viewmodel);
}

private List<Tuple<Book, InventoryDetail>> ListOfTuples_BookInventoryDetail(int count)
{
   var list_of_tuples = new List<Tuple<Book, InventoryDetail>>();

   var showbooks = webshopDB.Books
     .Join(webshopDB.InventoryDetails, b => b.BookId, i => i.BookId, (b, i) => new { b = b, i = i })
     .Where(o => (o.b.ShowInWebshop == true))
     .Where(o => o.b.BookThumbUrl.Contains(".jpg"))
     .OrderByDescending(o => o.b.OrderDetails.Count())
     .Take(count);         

  foreach (var item in showbooks)
  {
    list_of_tuples.Add( Tuple.Create<Book, InventoryDetail>( (item.b), (item.i) ) );
  }
  return list_of_tuples;
}
0 голосов
/ 16 ноября 2010

Запрос ответа SoftwareRockstar в LinqPad4 приводит к ошибкам!Так что это не так!

//This does works (in LinqPad4)    
from b in webshopDB.Books 
from i in webshopDB.InventoryDetails
where b.BookId == i.BookId
where b.ShowInWebshop == true 
select new { b.Title, i.Quantity, b.ShowInWebshop } 
0 голосов
/ 14 ноября 2010

Вы получаете книги, потому что вы указали это в своем Join утверждении с окончательным селектором => b.Вы хотите выбрать оба, поэтому используйте это:

var query = webshopDB.Books.Join(webshopDB.InventoryDetails,
                  b => b.BookId, i => i.BookId,
                  (b, i) => new { Book = b, InventoryDetail = i });

Затем, когда вы перебираете результаты, вы можете использовать:

foreach (var item in query)
{
    Console.WriteLine(item.Book.SomeProperty);
    Console.WriteLine(item.InventoryDetail.SomeProperty);
}

Другая проблема с вашим методом заключается в том, что тип возвращаемого значенияэто List<Book>.Таким образом, вышеприведенное не будет работать, поскольку класс Book отделен от класса InventoryDetail.Вам необходимо настроить новый класс, включающий оба, или использовать Tuple<Book, InventoryDetail> при использовании .NET 4.0.

Чтобы вернуть определенное свойство, вы можете изменить инструкцию на:

var query = webshopDB.Books.Join(webshopDB.InventoryDetails,
                  b => b.BookId, i => i.BookId,
                  (b, i) => new { b.BookId, i.Quantity });

Опять же, вам нужен соответствующий тип возврата, если вы возвращаете List<T>.

EDIT: чтобы получить Dictionary<Book, InventoryDetail>, вы можете использовать более ранний запрос следующим образом:

var query = webshopDB.Books.Join(webshopDB.InventoryDetails,
                  b => b.BookId, i => i.BookId,
                  (b, i) => new { Book = b, InventoryDetail = i })
              .ToDictionary(o => o.Book, o => o.InventoryDetail);

Конечно, вы можете использовать Where и Take по мере необходимости перед вызовом ToDictionary.Вы также можете проецировать только те свойства, которые вам нужны, как запрос непосредственно перед этим.Вам необходимо спроецировать его в анонимный тип с помощью ключевого слова new (раньше оно отсутствовало, поэтому взгляните на него еще раз).

0 голосов
/ 14 ноября 2010

Вы должны выбрать из обеих таблиц, например,

from b in webshop.Books
from i in webshopDB.InventoryDetails
where i.BookId = b.BookId
select b.BookId, b.Title, b.ShowInWebshop, i.InventoryDetailId, i.Quantity
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...