How to translate this SQL query to a LINQ query in EF Core?

后端 未结 2 1542
天涯浪人
天涯浪人 2021-01-21 11:28

I have the following table :

Indicators(A INT, B INT, C INT, D INT, TimeInsertedLocal DateTime) . 

And

相关标签:
2条回答
  • 2021-01-21 11:45

    It's literally one to one translation.

    SQL query

    SELECT A, B, C, D , TimeInsertedLocal
    FROM Indicators
    WHERE TimeInsertedLocal >= 
    (   
        SELECT MAX(I.TimeInsertedLocal) 
        FROM Indicators AS I
    )
    

    EF Core LINQ query:

    var indicators = dbContext.Set<Indicator>();
    var query = indicators
        .Where(i => i.TimeInsertedLocal >= indicators.Max(i2 => (DateTime?)i2.TimeInsertedLocal));
    

    EF Core generated SQL query:

    SELECT [i].[A], [i].[B], [i].[C], [i].[D], [i].[TimeInsertedLocal]
    FROM [Indicators] AS [i]
    WHERE [i].[TimeInsertedLocal] >= (
        SELECT MAX([i2].[TimeInsertedLocal])
        FROM [Indicators] AS [i2]
    )
    

    The only specific detail in LINQ query is the DateTime? cast inside Max, otherwise EF Core will try to emulate LINQ Max method throwing behavior and will evaluate query client side.

    0 讨论(0)
  • 2021-01-21 11:55

    Of course there are no indicators with a value of TimeInsertedLocal that is larger than the largest value of TimeInsertedLocal of all Indicators.

    However, it might be that you have several indicators with a value equal to the largest value of TimeInsertedLocal.

    If that is the case, you need to make groups of Indicators with the same TimeInsertedLocal, and take the group with the largest value.

    var indicatorsWithLargestTimeInsertedLocal = myDbContext.Indicators
        // make groups of Indicators with same TimeInsertedLocal:
        .GroupBy(indicator => indicator.TimeInsertedLocal)
    
        // put the group with the largest TimeInsertedLocal first:
        .OrderByDescending(group => group.Key)
    
        // The first group of indicators, is the group with the largest value of TimeInsertedLocal
        .FirstOrDefault();
    

    If you are certain the TimeInsertedLocal is unique, you don't have to GroupBy, there will only be one indicator with the largest TimeInsertedLocal

    var indicatorWithLargestTimeInsertedLocal = myDbContext.Indicators
        .OrderByDescending(indicator => indicator.TimeInsertedLocal)
        .FirstOrDefault();
    
    0 讨论(0)
提交回复
热议问题