【问题标题】:Linq group outer joins projected on a viewmodel投影在视图模型上的 Linq 组外连接
【发布时间】:2015-08-02 16:44:18
【问题描述】:

过去 2 天我一直在互联网上寻找解决方案,将以下 linq 查询分组到 BookId 上,但无济于事。该查询有效,但我想重新组织它,以便它可以按 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 到实体?请显示类(的基本部分),因为您应该尝试使用导航属性而不是连接来执行此操作。
  • @GertArnold 我已经添加了课程,谢谢
  • 为什么没有导航属性,比如Book.StockLogs
  • 事实是我没有想到:我已经为 stocklogs 中的书籍创建了导航 ID,这样可以更轻松地消除外部连接吗?
  • 我什至使 StockLogValue 成为 Books 的直接属性,无需引用另一个表。因为我在想的是原始库存更新存储在 stock 表中,然后将年份和月份附加到特定书籍的现有 stocklogvalue 中

标签: c# linq asp.net-mvc-viewmodel linq-group


【解决方案1】:

您的问题的直接解决方案是删除from a in b.DefaultIfEmpty() 行。一个join - intois 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() 
            });

我询问了导航属性,因为它们几乎总是使查询更容易编写,因为您不需要笨拙的joins。在你的情况下,差异并不是那么大。如果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() 
           });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多