2017-10-11 59 views
0

我有2个表_customerRepository.GetAllQueryable()_customerSettlementRepository.GetAllQueryable()在where子句中使用linq

在表_customerSettlementRepository.GetAllQueryable()中,我列了ApplyD (date),将这两者加在一起后,我想在where子句中找出​​max ApplyD。这是我的代码:

var settlements = from c in _customerRepository.GetAllQueryable() 
    join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC} 
    equals new {cs.CustomerMainC, cs.CustomerSubC} into c1 
    where cs.ApplyD == (c1.Select(b=>b.ApplyD).Max()) 
    select new CustomerSettlementViewModel() 
    { 
      TaxRate = cs.TaxRate 
    }; 
+1

添加例如输入和输出 – Backs

+0

问题不是很清楚,啥子你想究竟? – GGO

+0

简化查询。如果LINQ查询看起来很丑,那么生成的SQL和性能也会很糟糕。您将来无法保留此代码 –

回答

2

这是了不起,经常在这些问题的人想出了一个SQL(类似的)声明没有他们想要达成的目标规范。因此,不可能看到所提供的声明是否符合要求。

无论如何,看起来你有类似Customers(在CustomerRepository)和CustomerSettlementsCustomerSettlementRepository

CustomersCustomerSettlements都有一个CustomerMainC和一个CustomerSubC。您希望加入CustomersCustomerSettlements这两个属性。

A CustomerSettlement也有ApplyDTaxRate

你只是想保持连接结果,其中ApplyDApplyD

最大值最后,从每一个剩余的加入结果你想创建一个CustomerSettlementViewModel对象与将TaxRate在加入结果是值取自CustomerSettlement

现在我写了这篇文章,它让我很难理解为什么您需要首先加入,因为您只使用CustomerSettlements中的值,而不是Customer中的值。

此外,如果两个客户使用相同的CustomerSettlements加入。这将导致两个相等的CustomerSettlementViewModel对象。

但让我们假设这真的是你想要的。

在婴儿的步骤:

IQueryable<Customer> customers = ... 
IQueryable<CustomerSettlement> customerSettlements = ... 

var joinResults = customers.Join(customerSettlements 
    customer => new {customer.CustomerMainC, customer.CustomerSubC}, 
    settlement => new {settlement.CustomerMainC, settlement.CustomerSubC} 
    (customer, settlement) => new 
    { 
     settlement.ApplyD, 
     settlement.TaxRate, 
     // add other properties from customers and settlements you want in the end result 
    }); 

在口头上:采取一切Customers和所有CustomerSettlements。从每个Customer创建一个具有客户的CustomerMainCCustomerSubC的值的对象。每个CustomerSettlement都这样做。当这两个对象是相等的,创建一个新的对象,具有CustomerSettlementApplyDTaxRate(和其他属性您在最终结果需要)

注意,这仍然是一个IQueryable的值。尚未执行任何查询。

从这个joinResult你只想保留值为ApplyD的对象等于ApplyD的最大值。

This question on StackOverflow is about selecting the records with the max value。这个想法是将记录分组到ApplyD具有相同值的组中。然后按照键顺序排列组,并采取第一组。

var groupsWithSameApplyD = joinResults.GroupBy(
    joinedItem => joinedItem.ApplyD, 
    joinedItem => new CustomerSettlementViewModel() 
    { 
     TaxRate = orderedItem.TaxRate, 
     // add other values from joinedItems as needed 
    }); 

groupsWithSameApplyD中的每个组都有一个等于ApplyD的键。该组由CustomerSettlementViewModel对象组成,这些对象从组合的Key中的所有具有相同ApplyD的联合项创建。

现在为了通过降:

var orderedGroups = groupsWithSameApplyD.OrderByDescending(group => group.Key); 

第一组包含了最大的ApplyD所有元素。你想要的结果是组中元素的顺序。

如果根本没有组,则返回一个空序列。请注意,如果一个序列请求为结果,它始终是更好地返回一个空序列,而不是零,所以呼叫者可以在foreach使用返回的值,而无需检查返回null

var result = orderedGroups.FirstOrDefault() ?? 
    // if no groups at all, return empty sequence: 
    Enumerable.Empty<CustomerSettlementViewModel>(); 

注:FirstOrDefault是查询实际执行的第一步。如果需要,您可以将所有内容放入一个大查询中。不确定这是否会提高可读性和可维护性。

+0

非常感谢Harald Coppoolse,这对我非常有帮助 –

0

enter image description here

这是我的错误syntet,我需要写这一点,因为第一

var settlements = from c in _customerRepository.GetAllQueryable() 
        join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC} 
         equals new {cs.CustomerMainC, cs.CustomerSubC} 
        select new CustomerSettlementViewModel() 
        { 
         TaxRate = cs.TaxRate 
        }; 
       settlements = settlements.Where(p => p.ApplyD == settlements.Max(b => b.ApplyD));