EF Core自定義計數查詢

asp.net-core c# entity-framework-core linq

我正在開發一個小的ASP.NET Core項目,用於在Sqlite數據庫上使用Entity Framework Core標記圖像,主要用於學習。有兩個表(和POCO),標籤和圖像,其中多個標籤與每個圖像相關。我正在嘗試計算所有帶有與之關聯的標籤的圖像。

在簡單的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無法將結果映射到Tag。我也嘗試使用_context.Database.FromSql<int> ,但無法在其上找到任何真實的文檔,似乎沒有IntelliSense。

我現在所做的是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放在Debug輸出中的查詢:

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"

一般承認的答案

截至目前,您無法定義臨時結果。好消息是,它目前正在積壓: 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");

熱門答案

您原來的代碼行應該完全符合您的要求。它也建議使用內聯SQL。

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

你確定這稱為兩個表的數據庫,然後在內存中查詢它們嗎?如果您在調試時發現了這種行為,那麼您的檢查可能導致IQueryable枚舉哪個將使用不同於其他查詢的查詢來調用數據庫。

在不破壞正在運行的代碼的情況下檢查實際查詢的方法是使用Entity Framework Core文檔中的MyLoggerProvider

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

記錄器在代碼中註冊後,對服務器運行的任何SQL查詢都將顯示在控制台窗口和/或文件c:\ temp \ log.txt中。

在網站示例的數據庫表上使用Distinct()和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()而不是Select()。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow