Linq 组外连接投影在视图模型上
Linq group outer joins projected on a viewmodel
过去 2 天我一直在互联网上寻找解决方案,以找到对 BookId 上的以下 linq 查询进行分组的解决方案,但无济于事。查询有效,但我想重新组织它,以便它可以按 BookId 或 BookTitle 分组。
型号
Book(BookId, Title, Author, ISBN, Location, BookTypeId, StockLogValue)
Booktype(BookTypeId, BookTypeName)
Stock(StockId, bookId, quantity, date_added)
Transact (transactionId, TransactionTypeId, BookId, Quantity, TransactDate)
TransactionType( TransactionTypeId, TransactionTypeName)
控制器
public ActionResult Report(int? year, int? month, int? BkId)
{
var query = ReportYrMn( year, month, BkId);
return View(query);
}
public IEnumerable ReportYrMn(int? year, int? month, int? BkId)
{
var query =
(from bk in db.Books
join tr in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale") on bk.BookId equals tr.BookId into trs
from x in trs.DefaultIfEmpty()
join tr2 in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift") on bk.BookId equals tr2.BookId into trs2
from x2 in trs2.DefaultIfEmpty()
select new ReportViewModel { BookTitle = bk.BookTitle ,BookId = bk.BookId, StockLogValue=bksty.StockLogValue, SaleTotal = trs.Sum(c => c.TransactQty), GiftTotal = trs2.Sum(c => c.TransactQty), SalesCount = trs.Count(), GiftCount = trs2.Count() });
return query.AsEnumerable();
}
感谢您的帮助
您的问题的直接解决方案是删除 from a in b.DefaultIfEmpty()
行。 A join - into
is the same as GroupJoin
,创建与左侧项目相关的集合,即属于一本书的集合 Transacs
。这正是您想要的。
随后的 from
等同于 SelectMany
,它再次将这些集合展平,为您留下一个平展的图书交易行列表。
所以这会做你想做的事:
var query =
(from bk in db.Books
join tr in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
on bk.BookId equals tr.BookId into trs
join tr2 in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
on bk.BookId equals tr2.BookId into trs2
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = trs.Sum(c => c.TransactQty),
GiftTotal = trs2.Sum(c => c.TransactQty),
SalesCount = trs.Count(),
GiftCount = trs2.Count()
});
我询问了导航属性,因为它们几乎总是使查询更容易编写,因为您不需要笨拙的 join
s。就您而言,差异并不大。如果 Book
有导航 属性 Transacts
查询可能如下所示:
var query =
(from bk in db.Books
let sales = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
let gifts = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = sales.Sum(c => c.TransactQty),
GiftTotal = gifts.Sum(c => c.TransactQty),
SalesCount = sales.Count(),
GiftCount = gifts.Count()
});
过去 2 天我一直在互联网上寻找解决方案,以找到对 BookId 上的以下 linq 查询进行分组的解决方案,但无济于事。查询有效,但我想重新组织它,以便它可以按 BookId 或 BookTitle 分组。
型号
Book(BookId, Title, Author, ISBN, Location, BookTypeId, StockLogValue)
Booktype(BookTypeId, BookTypeName)
Stock(StockId, bookId, quantity, date_added)
Transact (transactionId, TransactionTypeId, BookId, Quantity, TransactDate)
TransactionType( TransactionTypeId, TransactionTypeName)
控制器
public ActionResult Report(int? year, int? month, int? BkId)
{
var query = ReportYrMn( year, month, BkId);
return View(query);
}
public IEnumerable ReportYrMn(int? year, int? month, int? BkId)
{
var query =
(from bk in db.Books
join tr in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale") on bk.BookId equals tr.BookId into trs
from x in trs.DefaultIfEmpty()
join tr2 in db.Transacts.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift") on bk.BookId equals tr2.BookId into trs2
from x2 in trs2.DefaultIfEmpty()
select new ReportViewModel { BookTitle = bk.BookTitle ,BookId = bk.BookId, StockLogValue=bksty.StockLogValue, SaleTotal = trs.Sum(c => c.TransactQty), GiftTotal = trs2.Sum(c => c.TransactQty), SalesCount = trs.Count(), GiftCount = trs2.Count() });
return query.AsEnumerable();
}
感谢您的帮助
您的问题的直接解决方案是删除 from a in b.DefaultIfEmpty()
行。 A join - into
is the same as GroupJoin
,创建与左侧项目相关的集合,即属于一本书的集合 Transacs
。这正是您想要的。
随后的 from
等同于 SelectMany
,它再次将这些集合展平,为您留下一个平展的图书交易行列表。
所以这会做你想做的事:
var query =
(from bk in db.Books
join tr in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
on bk.BookId equals tr.BookId into trs
join tr2 in db.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
on bk.BookId equals tr2.BookId into trs2
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = trs.Sum(c => c.TransactQty),
GiftTotal = trs2.Sum(c => c.TransactQty),
SalesCount = trs.Count(),
GiftCount = trs2.Count()
});
我询问了导航属性,因为它们几乎总是使查询更容易编写,因为您不需要笨拙的 join
s。就您而言,差异并不大。如果 Book
有导航 属性 Transacts
查询可能如下所示:
var query =
(from bk in db.Books
let sales = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "sale")
let gifts = bk.Transacts
.Where(a => a.TransactDate.Month == month && a.TransactDate.Year == year && a.TransactType.TransactTypeName == "gift")
select new ReportViewModel
{
BookTitle = bk.BookTitle,
BookId = bk.BookId,
StockLogValue=bksty.StockLogValue,
SaleTotal = sales.Sum(c => c.TransactQty),
GiftTotal = gifts.Sum(c => c.TransactQty),
SalesCount = sales.Count(),
GiftCount = gifts.Count()
});