Linq加入查询

时间:2010-11-14 16:44:18

标签: asp.net-mvc-2 linq-to-entities

例如 数据库有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

输出显示所有Book列和相关InventoryDe​​tails列(包括InventoryDe​​tails.BookId列) ..到现在为止还挺好 ... 尝试将此查询转换为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,而不是InventoryDe​​tail表格中的详细信息:数量

我忘了什么?

4 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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

答案 2 :(得分: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类分开,因此上述操作无效。您需要设置一个新类来包含它们,或者如果使用.NET 4.0则使用Tuple<Book, InventoryDetail>

要返回特定属性,您可以将语句修改为:

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

同样,如果您要返回List<T>,则需要适当的返回类型。

编辑:要获得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来电之前根据需要使用TakeToDictionary。您也可以在此之前仅将您需要的属性作为查询进行投影。您需要通过new关键字将其投影为匿名类型(之前已丢失,因此请再次查看)。

答案 3 :(得分:0)

在LinqPad 4中查询软件Rockstar的答案会产生错误!所以,那不是那样的!

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