在视图模型上投影的Linq组外连接

本文关键字:Linq 连接 投影 视图 模型 | 更新日期: 2023-09-27 18:05:53

在过去的两天里,我一直在互联网上寻找一个解决方案来对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(); 
    }

感谢您的帮助

在视图模型上投影的Linq组外连接

立即解决您的问题是删除from a in b.DefaultIfEmpty()行。join - intoGroupJoin相同,它创建与左侧项目相关的集合,即属于一本书的集合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() 
           });