我尝试将以下查询与针对Microsoft SQL Server 2016的Entity Framework Core结合使用:
SELECT [a], [b], [c]
FROM [x]
WHERE [a] = {0}
ORDER BY [b]
我像这样使用这个查询:
context.MySet.AsNoTracking()
.FromSql(MyQuery, aValue)
.Skip(pageSize * page)
.Take(pageSize)
.Select(x => x.ToJsonDictionary())
.ToList()
我在带有分页的.NET Core REST API中使用它,并且我希望对记录进行排序(按字母顺序排列)以使分页更加可用。 执行上述语句时出现以下错误:
ORDER BY子句在视图,内联函数中派生无效 表,子查询和公用表表达式,除非TOP,OFFSET 或者也指定了FOR XML。无效的NEXT选项用法 FETCH语句。 ORDER BY子句在视图中是无效的,内联 函数,派生表,子查询和公用表表达式, 除非还指定了TOP,OFFSET或FOR XML。无效的用法 FETCH语句中的选项NEXT。
在寻找类似问题时,我发现了其他一些帖子(1,2,3),但其中没有一个与EF Core结合使用和/或他们正在使用它在不同的情况下,在我的情况下不适用(例如子查询)。
我尝试使用EF的.OrderBy(..)
语法而不是查询中的ORDER BY
,但这并没有解决问题。我还尝试在查询TOP 100 PERCENT
之后添加SELECT
并与ORDRE BY
结合使用;这工作但没有订购专栏。它被忽略了。此限制在EF Limitations下描述。我还发现this post将TOP 100 PERCENT...
替换为TOP 99.99 PERCENT...
或TOP 9999999...
`。这似乎应该有效,但它并没有感觉到'对。
一般来说,这个问题将进一步解释为here。
摘要:不建议在视图中使用ORDER BY。使用ORDER BY 在观点之外。事实上,正确的设计意味着相同。如果 你使用TOP和Views,View很有可能 不返回表的所有行或将忽略ORDER BY 完全。
此外,我对#34; view"这个词感到困惑。对我来说,术语视图是指使用CREATE VIEW ..
语法创建的视图。是一个普通的,正常的' SQL查询还考虑了一个视图?或者EF Core是否在某种视图中包装请求,这是导致此错误的真正问题?
我不确定,但到目前为止所有的解决方案都是'我发现它看起来有点像hacky'。 想法?
答案 0 :(得分:4)
让我们稍微简化一下。以下是我的测试结果。我还添加了https://www.python.org/dev/peps/pep-0008/#prescriptive-naming-conventions。
class Program
{
static void Main(string[] args)
{
DbClient context = new DbClient();
var rawSql = "select [Id], [Title] from Post order by [Title]";
var query = context.Posts.AsNoTracking()
.FromSql(rawSql)
.Skip(1)
.Take(4)
.OrderBy(x => x.Title);
var generated = query.ToSql();
var results = query.ToList();
}
}
class DbClient : DbContext
{
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("conn_string");
}
}
class Post
{
public int Id { get; set; }
public string Title { get; set; }
public override string ToString() => $"{Id} | {Title}";
}
当我们查看generated
的值时,我们会看到query
的sql是什么:
SELECT [t].[Id], [t].[Title]
FROM (
SELECT [p].[Id], [p].[Title]
FROM (
select [Id], [Title] from Post order by [Title]
) AS [p]
ORDER BY (SELECT 1)
OFFSET 1 ROWS FETCH NEXT 4 ROWS ONLY
) AS [t]
ORDER BY [t].[Title]
请注意,有三个order by
子句,最里面的一个是来自rawSql
的子句。
我们可以查看错误消息,看看为什么它不合法:
ORDER BY子句在[...]子查询[...]中无效,除非还指定了OFFSET [...]。
的中间顺序包含偏移量,因此即使它在子查询中也有效。
要解决此问题,只需从rawSql
中删除排序,然后继续使用OrderBy()
linq方法。
var rawSql = "select [Id], [Title] from Post";
var query = context.Posts.AsNoTracking()
.FromSql(rawSql)
.Skip(1)
.Take(4)
.OrderBy(x => x.Title);
这会产生:
SELECT [t].[Id], [t].[Title]
FROM (
SELECT [p].[Id], [p].[Title]
FROM (
select [Id], [Title] from Post
) AS [p]
ORDER BY (SELECT 1)
OFFSET 1 ROWS FETCH NEXT 4 ROWS ONLY
) AS [t]
ORDER BY [t].[Title]
现在,所有order by子句都不在子查询中,或者有一个offset子句。