繁体   English   中英

EF Core自定义计数查询

[英]EF Core custom count query

我正在研究一个小型ASP.NET Core项目,该项目用于在Sqlite数据库上使用Entity Framework Core标记图像。 有两个表(和POCO),标签和图像,其中每个标签与多个标签相关。 我正在尝试对所有具有与之关联的标签的图像进行计数。

在普通的SQL中,我SELECT COUNT(DISTINCT ImageId) FROM Tags写入SELECT COUNT(DISTINCT ImageId) FROM Tags以获取计数,在LINQ中,我_context.Tags.Select(t => t.Image).Distinct().Count()_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()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM