开发者

Linq join query

For example DB with 2 Tables

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

The output shows all Book columns and related InventoryDetails columns (including the InventoryDetails.Boo开发者_开发技巧kId column) ..so far so good ... Trying to transform this query into a Linq one (using LinqPad, comparing several examples, common sense, etc.) I compilated the following generic List (because I wanted a present a list)

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
}

This module returns a list of books! Not the one I expected, though! It returns only book details such as Title and ShowOnSite NOT the details from the InventoryDetail table: Quantity

What do I forget?


The result how it works so far ...

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;
}


You need to select from both tables, e.g.

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


You're getting books because you specified that in your Join statement with the final selector of => b. You want to select both, so use this:

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

Then when you iterate over the results you can use:

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

The other problem with your method is that the return type is a List<Book>. So the above won't work since a Book class is separate from an InventoryDetail class. You need to setup a new class to encompass both, or use a Tuple<Book, InventoryDetail> if using .NET 4.0.

To return a particular property you could modify the statement to:

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

Again, you need an appropriate return type if you're returning a List<T>.

EDIT: to get a Dictionary<Book, InventoryDetail> you could use the earlier query as follows:

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);

Of course you can use the Where and Take as necessary before the ToDictionary call. You can also project just the properties you need as the query just before this one. You need to project it into an anonymous type via the new keyword (it was missing earlier so take another look at it).


Quering the answer of SoftwareRockstar in LinqPad4 generates errors! So, that's not the way!

//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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜