2016-09-17 130 views
2

我工作的一個小ASP.NET核心項目SQLite數據庫使用實體框架的核心標記圖像,主要只是爲了學習。有兩個表(和POCO),標籤和圖像,其中多個標籤與每個圖像相關。我試圖計算所有具有與它們關聯的標籤的圖像。EF核心的定製數查詢

在普通的SQL中,我會寫SELECT COUNT(DISTINCT ImageId) FROM Tags來獲得計數,而在LINQ中,我想出了_context.Tags.Select(t => t.Image).Distinct().Count()。但是,該LINQ查詢看起來會導致EF-Core連接兩個表,返回所有行,然後在代碼中執行DistinctCount

我試着做_context.Tags.FromSql("SELECT COUNT(DISTINCT ImageId) FROM Tags"),但由於該查詢僅返回計數,因爲EF不能結果標籤映射調用失敗。我也嘗試使用_context.Database.FromSql<int>,但無法找到任何真實文檔,並且似乎沒有IntelliSense。

我已經完蛋了,現在是什麼詳述此blog post from Eric Anderson的「ADO.NET」一節中:

int count; 
using (var connection = _context.Database.GetDbConnection()) 
{ 
    connection.Open(); 

    using (var command = connection.CreateCommand()) 
    { 
     command.CommandText = "SELECT COUNT(DISTINCT ImageId) FROM Tags"; 
     string result = command.ExecuteScalar().ToString(); 

     int.TryParse(result, out count); 
    } 
} 

但是,這是最好的方式去有效地得到計數?


編輯:下面是EF在調試輸出把查詢:

SELECT "t"."TagId", "t"."Content", "t"."ImageId", "t.Image"."ImageId", "t.Image"."FileName", "t.Image"."Path", "t.Image"."Url" 
FROM "Tags" AS "t" 
LEFT JOIN "Images" AS "t.Image" ON "t"."ImageId" = "t.Image"."ImageId" 
ORDER BY "t"."ImageId" 

回答

3

截至目前,不能定義一個特設的結果。 好消息是,它是目前積壓:https://github.com/aspnet/EntityFramework/issues/1862

在此期間,這裏是一個擴展方法,將工作:

public static int IntFromSQL(this ApplicationDbContext context, string sql) 
{ 
    int count; 
    using (var connection = context.Database.GetDbConnection()) 
    { 
     connection.Open(); 

     using (var command = connection.CreateCommand()) 
     { 
      command.CommandText = sql; 
      string result = command.ExecuteScalar().ToString(); 

      int.TryParse(result, out count); 
     } 
    } 
    return count; 
} 

用法:

int result = _context.IntFromSQL("SELECT COUNT(DISTINCT ImageId) FROM Tags"); 
0

你的代碼原有線路應已經完成了你想要的。它也將建議通過內聯SQL。

_context.Tags.Select(t => t.Image).Distinct().Count() 

您確定這稱爲兩個表的數據庫,然後在內存中查詢它們嗎?如果您在調試時觀察到了這種行爲,那麼您的檢查可能會導致IQueryable枚舉使用不同的查詢來調用數據庫,而不是使用其他查詢。

一種檢查實際查詢的方法,不用破壞運行代碼,通過使用實體框架核心文檔中的MyLoggerProvider

https://docs.efproject.net/en/latest/miscellaneous/logging.html?highlight=logging

一旦記錄器註冊代碼,然後任何SQL查詢運行對服務器將顯示在控制檯窗口和/或在文件C:\ TEMP \ log.txt中。

以下日誌消息使用網站上例的數據庫表的獨特()和一個Count()時生成的。

SELECT COUNT(*) 
FROM (
SELECT DISTINCT [a.Blog].[BlogId], [a.Blog].[Url] 
FROM [Posts] AS [a] 
INNER JOIN [Blogs] AS [a.Blog] ON [a].[BlogId] = [a.Blog].[BlogId] 
) AS [t]Closing connection to database '***' on server 'tcp:**************'. 

最後,因爲你不需要任何的t.image中的屬性的話,好像你應該使用一個Where(),而不是選擇()。

+0

我已將調試輸出中顯示的查詢添加到我的問題中。我只是跨過了LINQ調用,從來沒有進入它。但是我會設置日誌記錄並查看在Release中運行時寫入的內容。 –

+0

在調試或發佈中運行應該沒有什麼區別,但它值得一試。 – LittleDebugger

+0

奇怪的是,查詢包含一個order by。如果您刪除了選擇,結果如何? _context.Tags.Distinct()。Count() – LittleDebugger