EF Core 自定义计数查询

Dan*_*ier 3 c# linq entity-framework-core asp.net-core

我正在开发一个小型 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 连接两个表,返回所有行,然后在代码中执行Distinctand操作Count

我尝试这样做_context.Tags.FromSql("SELECT COUNT(DISTINCT ImageId) FROM Tags"),但由于该查询仅返回计数,因此调用失败,因为 EF 无法将结果映射到标签。我也尝试使用_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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但这是有效计数的最佳方法吗?


编辑:这是 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"
Run Code Online (Sandbox Code Playgroud)

小智 5

截至目前,您无法定义临时结果。好消息是它目前处于积压状态: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;
}
Run Code Online (Sandbox Code Playgroud)

用法:

int result = _context.IntFromSQL("SELECT COUNT(DISTINCT ImageId) FROM Tags");
Run Code Online (Sandbox Code Playgroud)