[英]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联接两个表,返回所有行,然后在代码中执行Distinct
和Count
。
我尝试做_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.