有没有一种方法可以在Select内的Select上添加where子句-我需要减少返回的JSON数量

时间:2019-05-13 07:04:33

标签: c# entity-framework lambda

这个问题是关于通过在我的Select上添加一个位置或完全重写查询,使我的代码返回较少的结果,从而使解决方案更有效的方法。

这是使用C#.NET Framework 4.7.2。 (我们尚未迁移到Core。)

我有以下实体:PERSON,PERSON_TYPE,COINS和FINANCIAL_YEAR。

  • 一个人有一个PERSON_TYPE(一对多),
  • 一个人有很多硬币(多对多的左侧),
  • 硬币有很多FINANCIAL_YEARS(多对多的右边)

(一个人也可以拥有一个或多个办公室,以保持完整性)

例如一个人可以拥有一组2016年的硬币10、2017年的29个硬币,2018年的37个硬币等等

我得到了返回的结果,但是在尝试过滤特定年份的结果时,我得到了所有返回的硬币,但只有我想懒加载的'FINANCIAL YEAR'。

我尝试了以下代码查询

    var persons = appCoreDBContext.PersonRepository.GetAll()
                  .Where(p => p.Active.Equals(true))
                  .Select(pl => new
                  {
                     pl,
                     PersonLocs = pl.PersonLocations.Where(ed => ed.EndDate != null)
                     .Select(o => new
                     {
                         o,
                         office = o.Office
                     }),
                     PersonType = pl.PersonType,
                     PersonCoins = pl.PersonCoins
                     .Select(yr => new
                     {
                         yr,
                         finYear = yr.FinancialYear
                     })
                     .Where(ee => ee.finYear.StartDate.Year == DateTime.Now.Year)
                  })
                  .AsEnumerable()
                  .Select(x => x.pl);

因此这将以JSON返回以下结果

[
  {
    "id": 1,
    "lastModifiedDate": "2019-05-09T11:47:10.193",
    "active": true,
    "firstName": "Fred",
    "lastName": "Flintstone",
    "title": "Mr",
    "email": "fred.flintstone@slaterockandgravel.com",    
    "personTypeId": 2,
    "personType": {
      "id": 2,
      "name": "Blue-Collar"
    },
    "personCoins": [
      {
        "id": 118,
        "lastModifiedDate": "2019-05-12T23:01:33.1566667",
        "active": true,
        "fullYearValue": 102.0,        
        "personId": 1,        
        "financialYearId": 19,
        "financialYear": {
          "id": 19,
          "lastModifiedDate": "2019-04-30T15:33:20.05",
          "active": true,
          "startDate": "2019-05-01T00:00:01",
          "endDate": "2020-04-30T00:00:00",
          "label": "FY 2019/2020"
        }
      },
      {
        "id": 1,
        "lastModifiedDate": "2019-04-29T07:49:41.367",
        "active": true,
        "fullYearValue": 85.0,        
        "personId": 1,        
        "financialYearId": 3,
        "financialYear": null
      },
      {
        "id": 2,
        "lastModifiedDate": "2019-04-29T07:50:14.747",
        "active": true,
        "fullYearValue": 65.0,        
        "personId": 1,        
        "financialYearId": 2,
        "financialYear": null
      },
      {
        "id": 3,
        "lastModifiedDate": "2019-04-29T07:50:41.307",
        "active": true,
        "fullYearValue": 45.0,        
        "personId": 1,        
        "financialYearId": 1,
        "financialYear": null
      },
      {
        "id": 109,
        "lastModifiedDate": "2019-05-09T18:02:34.52",
        "active": true,
        "fullYearValue": 100.0,        
        "personId": 1,        
        "financialYearId": 20,
        "financialYear": null
      },
      {
        "id": 112,
        "lastModifiedDate": "2019-05-09T19:00:09.787",
        "active": true,
        "fullYearValue": 101.0,        
        "personId": 1,       
        "financialYearId": 21,
        "financialYear": null
      },
      {
        "id": 115,
        "lastModifiedDate": "2019-05-09T19:04:15.853",
        "active": true,
        "fullYearValue": 101.0,        
        "personId": 1,       
        "financialYearId": 22,
        "financialYear": null
      }
    ],
    "personLocations": [
      {
        "id": 1,
        "lastModifiedDate": "2019-04-25T10:19:07.193",
        "active": true,
        "startDate": "2018-10-29T09:00:00",
        "endDate": null,
        "office": {
          "id": 2,
          "lastModifiedDate": "2019-04-25T10:16:37.9533333",
          "active": true,
          "name": "Bedrock",
          "address1": "The Quarry",
          "address2": "Bedrock",
          "address3": "Prehistorica",
          "zipcode": "YabbaDabbaDoo",
          "openingDate": "1992-06-01T09:00:00",
          "closingDate": null,
          "officialCurrencyId": 1,
          "officialCurrency": null,
          "countryId": 1,
          "country": null
        }
      }
    ]
  }
]

正如您在上面看到的那样,我确实获得了我想要的2019年的会计年度信息,但是我也获得了我不想获得的其他会计年度的所有其他COIN数据,这使得响应变大了。

我想要让我的返回结果看起来像这样

    [
  {
    "id": 1,
    "lastModifiedDate": "2019-05-09T11:47:10.193",
    "active": true,
    "firstName": "Fred",
    "lastName": "Flintstone",
    "title": "Mr",
    "email": "fred.flintstone@slaterockandgravel.com",    
    "personTypeId": 2,
    "personType": {
      "id": 2,
      "name": "Blue-Collar"
    },
    "personCoins": [
      {
        "id": 118,
        "lastModifiedDate": "2019-05-12T23:01:33.1566667",
        "active": true,
        "fullYearValue": 102.0,        
        "personId": 1,        
        "financialYearId": 19,
        "financialYear": {
          "id": 19,
          "lastModifiedDate": "2019-04-30T15:33:20.05",
          "active": true,
          "startDate": "2019-05-01T00:00:01",
          "endDate": "2020-04-30T00:00:00",
          "label": "FY 2019/2020"
        }
      }
    ],
    "personLocations": [
      {
        "id": 1,
        "lastModifiedDate": "2019-04-25T10:19:07.193",
        "active": true,
        "startDate": "2018-10-29T09:00:00",
        "endDate": null,
        "office": {
          "id": 2,
          "lastModifiedDate": "2019-04-25T10:16:37.9533333",
          "active": true,
          "name": "Bedrock",
          "address1": "The Quarry",
          "address2": "Bedrock",
          "address3": "Prehistorica",
          "zipcode": "YabbaDabbaDoo",
          "openingDate": "1992-06-01T09:00:00",
          "closingDate": null,
          "officialCurrencyId": 1,
          "officialCurrency": null,
          "countryId": 1,
          "country": null
        }
      }
    ]
  }
]

E.G。它只是返回指定年份的硬币数据。

当我在分页的JQuery Datatable中显示此数据时,我立即获得了所有结果,并且数据库中有5000个人,因此返回了一个非常大的JSON文件。

有没有一种方法可以在子选择内的此查询上添加Where子句,或者通过另一种方法获取数据,这将更加有效。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您只需在财务年度部分添加一个where子句即可:

var persons = appCoreDBContext.PersonRepository.GetAll()
              .Where(p => p.Active.Equals(true))
              .Select(pl => new
              {
                 pl,
                 PersonLocs = pl.PersonLocations.Where(ed => ed.EndDate != null)
                 .Select(o => new
                 {
                     o,
                     office = o.Office
                 }),
                 PersonType = pl.PersonType,
                 PersonCoins = pl.PersonCoins
                 .Where(yr => yr.FinancialYear != null)
                 .Select(yr => new
                 {
                     yr,
                     finYear = yr.FinancialYear
                 })
                 .Where(ee => ee.finYear.StartDate.Year == DateTime.Now.Year)
              })
              .AsEnumerable()
              .Select(x => x.pl);

答案 1 :(得分:0)

问题是您试图对数据进行子过滤,但是最后您选择并使用.Select(x => x.pl)

序列化了完整的Person实体及其所有相关实体

尝试一下:

.Select(pl => new PersonViewModel
{
    pl.id,
    pl.lastModifiedDate,
    pl.active,
    pl.firstName,
    pl.lastName,
    pl.email,
    pl.personType.Select(pt => new PersonTypeViewModel
    {
       pt.id,
       pt.name
    }),             
    personLocs = pl.PersonLocations.Where(ed => ed.EndDate != null)
        .Select(o => new PersonLocationViewModel
        {
           id = o.OfficeId,
           office = o.Office
        }),
    personCoins = pl.PersonCoins
       .Select(yr => new PersonCoinViewModel
       {
           finYear = yr.FinancialYear
       })
       .Where(ee => ee.finYear.StartDate.Year == DateTime.Now.Year)
 }).AsEnumerable();

您将需要为要发送回的数据结构定义视图模型,因为我认为您无法返回/序列化匿名类型。

基本上,只需选择要不选择实体的字段和相关数据即可。您应该避免返回实体,包括在返回的DTO / ViewModel内部引用实体,因为这将包括序列化实体中可用的所有数据和相关数据。这可能会触发延迟负载(性能问题),并且向客户端发送的数据要多于您所需要的,或者希望向潜在的恶意用户公开。