2017-06-13 65 views
0

我們有一個包含數千個條目的數據庫。我們希望通過其名稱獲得特定項目的「排名位置」。如何在SQL數據庫中使用實體框架獲取行索引而不查詢所有數據?

由於存在大量數據,我們希望避免將查詢所有數據以確定行索引(例如使用ToList()IndexOf())。

我嘗試使用

 List<Ranking> ranking = _context.Testes 
      .OrderByDescending(t => t.Val) 
      .Select((d, i) => new Ranking() { 
       Name = d.Name, 
       Ranking= i 
      }).First(d=>d.Name = "Test"); 

,但我得到這個錯誤:

'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[WebApplication4.Models.Teste]).OrderByDescending(t => t.Val).Select((d, i) => new Ranking() {Name = d.Name, Ranking = i})': This overload of the method 'System.Linq.Queryable.Select' is currently not supported.

這有可能以某種方式?

+0

跳過並取走尋呼? – ErikEJ

+0

跳過並取得將獲得列表中的第n個位置。我想提供一個「名稱」並查詢它的排名位置。 –

+2

你不能把這個'Select()'重載翻譯成SQL。 ORM不適用於報告,這是100%的報告查詢。 SQL Server提供了諸如'ROW_NUMBER','RANK'和'DENSE_RANK'等排名函數。您可以創建一個視圖來計算排名並將排名映射到它,例如'CREATE VIEW排名AS SELECT名稱,RANK OVER(ORDER BY Val)排名來自測試'。 EF可能會按照慣例將'Ranking'類映射到'Rankings'視圖。如果沒有,則使用'Table'屬性映射它 –

回答

3

您不能將此Select()重載轉換爲SQL。 ORM不適用於報告,這是100%的報告查詢。

SQL Server提供ranking functions,如ROW_NUMBER,RANK和DENSE_RANK。你可以創建一個計算排名的景色,你的排名映射到它,比如:

CREATE VIEW Rankings 
AS 
SELECT 
    Name, 
    DENSE_RANK() OVER(ORDER BY Val) Ranking 
From Tests 

DENSE_RANK()將返回相同的排名,如果兩個記錄領帶和繼續下一個排名。 ROW_NUMBER只會使用遞增數字。如果您使用ROW_NUMBER,則應該使用附加的排序標準以避免爲關係生成隨機排名。

EF可能會按照慣例將排名類映射到排名視圖。如果不是,您可以使用表屬性或ToTable地圖,如果你使用代碼優先配置:

[Table("Rankings") 
public class Ranking 
{ 
    public string Name{get;set;} 
    public int Ranking {get;set;} 
} 

檢索特定的排名只需要Where()條款:

var someRanking=context.Rankings.Where(r=>r.Name=someName); 
1

在LINQ類似(注你必須處理的關係得到一個明確的排名)

  var q = from t in db.Testes 
        where t.Name == "whatever" 
        select new 
         { 
         Testes =t, 
         Rank =1+db.Testes.Where(ot => ot.Val < t.Val || (ot.Val == t.Val && ot.Id < t.Id)).Count() 
         }; 

它轉換爲

SELECT 
    [Project1].[Id] AS [Id], 
    [Project1].[Val] AS [Val], 
    [Project1].[Name] AS [Name], 
    1 + [Project1].[C1] AS [C1] 
    FROM (SELECT 
     [Extent1].[Id] AS [Id], 
     [Extent1].[Val] AS [Val], 
     [Extent1].[Name] AS [Name], 
     (SELECT 
      COUNT(1) AS [A1] 
      FROM [dbo].[Testes] AS [Extent2] 
      WHERE ([Extent2].[Val] < [Extent1].[Val]) OR (([Extent2].[Val] = [Extent1].[Val]) AND ([Extent2].[Id] < [Extent1].[Id]))) AS [C1] 
     FROM [dbo].[Testes] AS [Extent1] 
     WHERE N'whatever' = [Extent1].[Name] 
    ) AS [Project1] 
相關問題