linq查询问题

时间:2018-12-26 00:29:40

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

我正试图通过Linq查询从数据库中获取按月组织的一些特定值,但是我遇到了一些麻烦,我不知道为什么会发生这种情况。

数据的组织方式如下:

票证有很多产品,而 Worker 有许多票证,并且 Shop 有许多工人,而管理员用户有很多商店。它存在一个名为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',因为已实现   值是null。结果类型的通用参数或查询   必须使用可为空的类型。

2 个答案:

答案 0 :(得分:0)

我认为,问题出在这里

from django.conf import settings

class MyView(ListView):
    permission_denied_message = 'Hooo!'

    def get_permission_denied_message(self):
        perms = self.get_permission_required()
        if settings.DEBUG:
            for perm in perms:
                if not self.request.user.has_perm(perm):
                    return 'Permission denied: ' + str(perm)
        return ''

当您没有用于此条件的数据时,SQL将返回null,但是{% if exception and debug %} <h3 class="font-bold">{{ exception }}</h3> {% endif %} 属性不为null,因此请更改查询,如下所示:

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

答案 1 :(得分:0)

弹出几个问题:

 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) 由于看起来您的商店已与Tickets集合映射,因此不需要这些显式联接。就我个人而言,我不使用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();

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