EF7
引入了返回标量类型的原始 SQL
查询。 这在 EF8
中得到了增强,包括返回任何可映射 CLR
类型的原始 SQL
查询,而无需在 EF
模型中包括该类型。
使用非映射类型的查询是使用 SqlQuery
或 SqlQueryRaw
执行的。 前者使用字符串内插来参数化查询,这有助于确保所有非常量值都被参数化。
var result = _dbContext.Database.SqlQuery<Blog>($"select * from {typeof(Blog).Name}").ToList();
非常振奋人心的是,SqlQuery
的得到的结果是一个IQueryable
,也就是说,可以无缝对接Linq
!
所以你可以这样,在Sql
中直接写上你的条件:
var cutoffDate = new DateOnly(2022, 1, 1);
var summaries =
await context.Database.SqlQuery<PostSummary>(
@$"SELECT b.Name AS BlogName, p.Title AS PostTitle, p.PublishedOn
FROM Posts AS p
INNER JOIN Blogs AS b ON p.BlogId = b.Id
WHERE p.PublishedOn >= {cutoffDate}")
.ToListAsync();
或者这样,使用Sql
拼接表,再用Linq
进行筛选:
var summariesIn2022 =
await context.Database.SqlQuery<PostSummary>(
@$"SELECT b.Name AS BlogName, p.Title AS PostTitle, p.PublishedOn
FROM Posts AS p
INNER JOIN Blogs AS b ON p.BlogId = b.Id")
.Where(p => p.PublishedOn >= cutoffDate && p.PublishedOn < end)
.ToListAsync();
到目前为止,所有查询都是直接针对表执行的。 SqlQuery
也可用于在不映射 EF
模型中的视图类型的情况下从视图返回结果。 例如:
var summariesFromView =
await context.Database.SqlQuery<PostSummary>(
@$"SELECT * FROM PostAndBlogSummariesView")
.Where(p => p.PublishedOn >= cutoffDate && p.PublishedOn < end)
.ToListAsync();
甚至是函数:
var summariesFromFunc =
await context.Database.SqlQuery<PostSummary>(
@$"SELECT * FROM GetPostsPublishedAfter({cutoffDate})")
.Where(p => p.PublishedOn < end)
.ToListAsync();
亦或者是存储过程:
var summariesFromStoredProc =
await context.Database.SqlQuery<PostSummary>(
@$"exec GetRecentPostSummariesProc")
.ToListAsync();