2010-11-14 3 views
1

Например DB с 2 ТаблицыLinq запрос присоединиться к

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

Execute: 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: Количество

Что я могу забыть?

ответ

1

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

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

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

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 
+0

Quering вашего ответа генерирует ошибку! Следующие работы (в LinqPad4): от b в книгах от i в InventoryDetails где b.BookId == i.BookId где b.ShowInWebshop == true select new {b.Title, i.Quantity} – KWHJ

+0

Да, это правильно , Извините за недосмотр; В то время, когда я отправил ответ, у меня не было LinqPad или другого инструмента для разработки. – SoftwareRockstar

0

Вы получаете книги, потому что вы указали, что в вашем 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

@ user507458: Я раньше не встречал ключевое слово 'new'. Взгляните на мое изменение выше для решения «ToDictionary». Помните, что это будет работать, только если у вас есть уникальные ключи. Также вам нужно изменить свой тип возврата на «Словарь » или любые типы, которые вы решите вернуть. –

+0

Hi Ahmad Mageed, Тем временем мне удалось вернуть тип Tuple с помощью метода Tuple.Create (book, inventorydetail) :). Однако он возвращает только последнюю запись в базе данных. Итак, я должен выяснить, как получить всю «книгу» и «инвентарь». Особенно, если я хочу добавить дополнительное соединение (например, в OrderDetail). Поэтому я реализовал словарь типа возврата (THX для вашей любезной помощи). – KWHJ

+0

Итак, остается вопрос: как получить объект Book (как ключ) и объект InventoryDetail (как значение) из словаря (или в случае Tuple: элементы) и правильно сохранить их в ViewModel? – KWHJ

0

Quering ответ 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 } 
Смежные вопросы