2012-02-10 8 views
12

データベースに保存されている記事を出版日の降順で注文し、記事の後ろの最初の20レコードをId == 100とする必要があります。リスト全体をメモリにロードせずに、LinqでSqlにSkipWhileを実装する方法は?

これは私がLINQのをどうしたいものです。SkipWhileは、LINQ to SQLは(hereを参照)でサポートされていないため

IQueryable<Article> articles = 
    db.Articles 
    .OrderByDescending(a => a.PublicationDate) 
    .SkipWhile(a => a.Id != 100) 
    .Take(20); 

しかし、これは非サポート例外を生成します。

IEnumerable<ArticleDescriptor> articles = 
    db.Articles 
    .OrderByDescending(a => a.PublicationDate) 
    .ToList() 
    .SkipWhile(a => a.Article.Id != 100) 
    .Take(20); 

しかし、これは私が最初にメモリに全体の順序付きリストをロードし、1の後に20件の記事を取る必要があることを意味:

可能な解決策は、クエリを実行し、オブジェクトするのLINQを使用してSkipWhileを適用することですId == 100となります。

このような膨大なメモリ消費を避ける方法はありますか?

さらに一般的に、これをSQLで実現するにはどうすればよいですか?

+1

興味深い要件のように試すことができます。 'Id'と' PublicationDate'との間には何らかの関係がありますか?あなたが本当にやりたいことは、日付で注文し、「Id」、「100」、そして次に* 20を取るまで、そのリストに沿って行くのですか? – AakashM

+0

はい、まさに私が欲しいものです。 'Id'と' PublicationDate'との間には関係がありません。この要件の理由は、特定の記事の後に発行された特定の数の記事を取得する必要があるということです。その記事のうち、「Id」だけがわかっています。もちろん、その記事の「出版日」を知っていれば、はるかに簡単です。 –

答えて

5

私は列名から推測しているとして、場合、PublicationDateが変化しない、あなたは、2つの個別のクエリでこれを行うことができます:

  • Id == 100
  • ArticlePublicationDateを確立

  • その日付以降

のような何かから20件の記事を取得します

var articles = 
    db.Articles 
    .Where(a => a.PublicationDate 
      <= db.Articles.Single(aa => aa.Id == 100).PublicationDate) 
    .OrderByDescending(a => a.PublicationDate) 
    .Take(20); 

けど、それはそれはあまりにも複雑である:

var thresholdDate = db.Articles.Single(a => a.Id == 100).PublicationDate; 
var articles = 
    db.Articles 
    .Where(a => a.PublicationDate <= thresholdDate) 
    .OrderByDescending(a => a.PublicationDate) 
    .Take(20); 

はそれも、LINQ to SQLは、これを翻訳できるということかもしれません。それを試してみてください。

+0

私はこれが(@Atzoyaによっても投稿された)良いソリューションだと思います。これはデータベースのストアドプロシージャにも移動できます。私は単一のSQLクエリではできないと思います。ここでの唯一の問題は、(まれではない)イベントで、異なるIDを持つ多数の記事が同時に掲載されていることです。しかし、これを整理するために、IDを降順に並べるなど、記事を取得する際に追加の注文ルールに同意する必要があります: db.Articles 。 Id <100) .OrderByDescending(a => a.PublicationDate).ThenByDescending(a => a.Id) .Take(20); ' –

+0

私は試してみました。 LINQ to SQLは、LINQクエリ全体を単一のSQLクエリに変換することさえ管理します。 –

+0

これを回答として受け入れるために、Single(a => a.Id == 100)をSingle(aa => aa.Id == 100)に置き換えることをお勧めしますか? –

0

where文を追加するだけの解決策ではありませんか?

IQueryable<Article> articles = db.Articles.Where(a => a.id != 100).OrderByDescending(a => a.PublicationDate).Take(20); 
+0

ええ、私もそう思っていましたが、実際の要件を見てください:日付で注文し、あなたが100になるまでそのリストに進み、**その後、次の20を取る。 – AakashM

+1

記事5が公開された後、記事10(例えば、ドラフトに載っているため) –

+0

の場合、これはうまくいきません。 – Tan

1

あなたはこの

var articles = 
    db.Articles 
    .Where(a => a.PublicationDate < db.Articles 
            .Where(aa => aa.Id==100) 
            .Select(aa => aa.PublicationDate) 
            .SingleOrDefault()) 
    .OrderByDescending(a => a.PublicationDate) 
    .Take(20); 
+0

+1これはAakashMが投稿したのと同じ解決策ですが、もう1つは明確な説明があるためです –

関連する問題