繁体   English   中英

实体框架核心; 在对(MS)SQL Server的查询中使用ORDER BY

[英]Entity Framework Core; using ORDER BY in query against a (MS) SQL Server

我正在尝试对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中使用了此功能,并且希望对记录进行排序(按字母顺序),以使分页功能更加有用。 执行以上语句时出现以下错误:

除非还指定了TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公共表表达式中无效.FETCH语句中选项NEXT的无效用法。 除非还指定了TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公共表表达式中无效.FETCH语句中选项NEXT的无效用法。

寻找类似的问题,我发现这些一些其他职位( 123 ),但其中没有一个与EF核心的组合,其中使用和/或它们在不同的环境中使用它不以我的情况下(例如,子查询)申请。

我试图在查询中使用EF的.OrderBy(..)语法,而不是在ORDER BY中使用,但这不能解决问题。 我还尝试将查询中的SELECT之后的TOP 100 PERCENTORDRE BY结合使用; 这行得通,但没有订购该专栏。 它只是被忽略了。 此限制在EF限制下进行描述。 我还发现此帖子TOP 99.99 PERCENT...TOP 9999999...代替TOP 100 PERCENT... 这似乎应该起作用,但是并不“感觉”正确。 一般而言,此问题将在此处进一步说明。

摘要:建议不要在View中使用ORDER BY。 在视图外使用ORDER BY。 实际上,正确的设计意味着相同。 如果将TOP与Views一起使用,则很有可能View不会返回表的所有行或将完全忽略ORDER BY。

此外,我对“视图”一词感到困惑。 对我而言,术语“视图”是指使用CREATE VIEW ..语法CREATE VIEW .. 普通的“正常” SQL查询是否也被视为视图? 还是EF Core将请求包装在某种视图中,这才是导致此错误的真正问题?

我不确定,但是到目前为止,我发现的所有“解决方案”似乎都有些“ hacky”。 思考?

让我们简化一下。 这就是我要进行测试的内容。 我还添加了一些代码,用于打印从EF查询生成的sql

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子句在子查询[...]中无效。

中间顺序by 确实包含偏移量,因此即使它在子查询中也有效。

要解决此问题,只需从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子句。

暂无
暂无

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

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