Microsoft SQL Server2016に対してEntityFrameworkCoreと組み合わせて次のクエリを使用しようとしています。
_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()
_
これを.NETCore REST API with paginationで使用し、ページネーションをより使いやすくするためにレコードを(アルファベット順に)ソートしたいのですが。上記を実行すると次のエラーが発生します。ステートメント:
ORDER BY句は、TOP、OFFSET、またはFOR XMLも指定されていない限り、ビュー、インライン関数、派生テーブル、サブクエリ、および共通テーブル式では無効です。FETCHステートメントでのオプションNEXTの使用が無効です。 ORDER BY句は、TOP、OFFSET、またはFOR XMLも指定されていない限り、ビュー、インライン関数、派生テーブル、サブクエリ、および共通テーブル式では無効です。FETCHステートメントでのオプションNEXTの使用が無効です。
同様の問題を探して、私はこれらの他のいくつかの投稿( 1 、 2 、)を見つけましたが、EFCoreと組み合わせて使用されたものはありません/または、私の場合には当てはまらない別のコンテキスト(サブクエリなど)で使用していました。
クエリの_ORDER BY
_ではなくEFの.OrderBy(..)
構文を使用しようとしましたが、これで問題が解決しません。また、クエリのSELECT
の後に_TOP 100 PERCENT
_を_ORDRE BY
_と組み合わせて追加してみました。これは機能しましたが、列を注文しませんでした。無視されただけです。この制限については、 EF制限 で説明されています。また、_TOP 100 PERCENT...
_を_TOP 99.99 PERCENT...
_または_TOP 9999999...
_ `に置き換える この投稿 も見つかりました。これはうまくいくはずのようですが、正しく感じられません。この問題は一般的にさらに説明されています ここ 。
概要:ビューでORDERBYを使用することはお勧めできません。ビューの外でORDERBYを使用します。実際、正しい設計は同じことを意味します。 TOPをViewsと一緒に使用すると、Viewがテーブルのすべての行を返さないか、ORDERBYを完全に無視する可能性が高くなります。
さらに、私は「ビュー」という言葉に混乱しています。私にとって、ビューという用語は、_CREATE VIEW ..
_構文によって作成されたビューの使用法を指します。プレーンな「通常の」SQLクエリもビューと見なされますか?または、EF Coreがリクエストを何らかのビューでラップしていて、これがこのエラーの原因となっている本当の問題ですか?
よくわかりませんが、これまでのところ、私が見つけたすべての「解決策」は一種の「ハッキー」のようです。考え?
少し単純化しましょう。これが私がテストのために思いついたものです。また、 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]
_
3つの_order by
_句があり、最も内側の句はrawSql
からのものであることに注意してください。
エラーメッセージを見て、それが合法でない理由を確認できます。
[...]サブクエリ[...]では、OFFSET [...]も指定されていない限り、ORDERBY句は無効です。
doesによる中間の順序にはオフセットが含まれているため、サブクエリ内にある場合でも有効です。
これを修正するには、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句はサブクエリに含まれていないか、オフセット句があります。