【问题标题】:Problems with a linq querylinq 查询的问题
【发布时间】:2018-12-26 00:29:39
【问题描述】:

我正在尝试使用 Linq 查询从我的数据库中按月组织一些特定值,但我遇到了一点麻烦,我不知道为什么会发生这种情况。

数据是这样组织的:

一个工单有很多产品,一个工人有很多工单,一个商店有很多工人,一个管理员用户有很多商店。它存在一个名为 Shops_Workers 的表,我可以在其中创建与商店和工人的关系。 Ticket 有一个带有创建日期的字段和另一个名为 Points 的字段,它为该票提供一个整数值。我需要获得每个工人为每个月有一个用户的所有商店创建的所有票的所有积分的总和。

我正在使用 EntityFramework 并尝试进行 linq 查询以获取所有数据,因此我创建了一些 DateTime 字段来获取月份并对我的 linq 查询进行子查询,但我不知道是否这可以正常工作。

 Int32? admin = getCurrentUser();
 DateTime TmpYear = DateTime.Now;

 var result = (from s in _db.Shops
                      join t in db.Tickets on s.IdShop equals t.IdTicket
                      join sw in db.Shop_Worker on s.IdShop equals sw.IdShop
                      join u in db.Users on sw.IdUser equals u.IdUser
                      where u.IdUser == admin
                      select new {
                          Jan = s.Tickets.Where(x => x.SellDate.Value.Month == this.Jan.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Feb = s.Tickets.Where(x => x.SellDate.Value.Month == this.Feb.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Mar = s.Tickets.Where(x => x.SellDate.Value.Month == this.Mar.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Ap = s.Tickets.Where(x => x.SellDate.Value.Month == this.Ap.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          May = s.Tickets.Where(x => x.SellDate.Value.Month == this.May.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Jun = s.Tickets.Where(x => x.SellDate.Value.Month == this.Jun.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Jul = s.Tickets.Where(x => x.SellDate.Value.Month == this.Jul.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Au = s.Tickets.Where(x => x.SellDate.Value.Month == this.Au.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Sep = s.Tickets.Where(x => x.SellDate.Value.Month == this.Sep.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Oct = s.Tickets.Where(x => x.SellDate.Value.Month == this.Oct.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Nov = s.Tickets.Where(x => x.SellDate.Value.Month == this.Nov.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                          Dec = s.Tickets.Where(x => x.SellDate.Value.Month == this.Dec.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum(),
                      });

我有一个 System.Collections.ListDictionaryInternal 错误,带有消息:

转换为值类型“System.Int32”失败,因为物化了 值为空。结果类型的泛型参数或查询 必须使用可空类型。

【问题讨论】:

    标签: c# sql-server entity-framework linq datetime


    【解决方案1】:

    出现了几个问题:

     Int32? admin = getCurrentUser();
    

    在尝试在查询中使用管理员用户之前,请先声明您恢复了管理员用户,然后在查询中使用 admin.Value。

    var result = (from s in _db.Shops
                          join t in db.Tickets on s.IdShop equals t.IdTicket
    

    这里的商店和门票是交叉键连接的。 (IdShop 到 IdTicket) 由于看起来您的 Shop 与门票集合映射,因此不需要这些显式连接。就我个人而言,我不使用 linq-QL 语法,因为我发现流畅的方法更易于遵循和结构化,将两者混合会让人感到困惑。

    我可能会考虑拆分操作,首先获取按月分组的适当数据,然后将其转换为所需的数据结构。 Linq 很棒,但是试图在一个表达式中做太多事情会使其更难理解。可能需要进行一些简化,但希望这能给您一些关于如何处理转换的想法。

    var totalTickets = _db.Shops.Where(s => s.ShopWorkers.Any(sw => sw.IdUser == admin.Value))
        .SelectMany(s => s.Tickets.Where(t => t.SellDate.HasValue && t.SellDate.Value.Year == tmpYear.Year))
        .Select(t => new {Month = t.SellDate.Value.Month, t.Points})
        .GroupBy(x => x.Month)
        .Select(x => new {Month = x.Key, TotalPoints = x.Sum(g => g.Points)).ToList();
    

    我是从内存中提取的,因此可能需要进行一些调整,但主要是提取工作人员包含当前用户的商店,然后选择这些商店在指定年份的所有票,从中我们想要月份和积分值。我们按月分组,然后用该组的点数总和选择该组(月)。你应该得到每个月售出门票的清单。这不包括没有售出门票的月份,因此您需要在零月份的集合中联合以获取完整列表。从中,您应该能够使用每个月的值作为属性填充结构。

    【讨论】:

      【解决方案2】:

      我想,问题就在这里:

      Jan = s.Tickets.Where(x => x.SellDate.Value.Month == this.Jan.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => e.Points).Sum()
      

      当你没有这个条件的数据时,SQL会返回null,但是Jan属性不为null,所以改变查询如下:

      Jan = s.Tickets.Where(x => x.SellDate.Value.Month == this.Jan.Month && x.SellDate.Value.Year == TmpYear.Year).Select(e => (int?)e.Points).Sum() ?? 0
      

      【讨论】:

      • 这是一个好主意,至少现在它不会给我一个错误,但是我在我的数据库上进行了查询,其中 Shops 表将这些表连接起来,并将一月参数添加到 WHERE 语句中我在 Linq 上编码的子查询中,我得到了响应,它不为空。所以我认为我可能在做一个糟糕的 Linq 查询,但我不知道错误可能出在哪里。
      猜你喜欢
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多