1

私が取り組んでいるプロジェクトには、OData レイヤーの上に Entity Framework があります。Odata レイヤーでは、サーバー側のページネーションが の値になっています75。この件に関する私の読書は、このページネーションの値がテーブルごとではなく、全面的に使用されていると私に信じさせます。現在、すべてのデータを抽出しようとしているテーブルは、もちろん 75 行を超えています。エンティティ フレームワークを使用すると、私のコードは次のようになります。

public IQueryable<ProductColor> GetProductColors()
{
   return db.ProductColors;
}

dbエンティティ コンテキストはどこにありますか。これは、最初の 75 レコードを返しています。次のコードを提供するためにパラメーターinlinecountセットを追加できる場所を読みました。allpages

public IQueryable<ProductColor> GetProductColors()
{
   return db.ProductColors.AddQueryOption("inlinecount","allpages");
}

ただし、これも 75 行を返します。

OData サーバー側のページネーションに関係なく、すべてのレコードを真に取得する方法を明らかにできる人はいますか?

重要:ページネーションを削除したり、オフにしたりすることはできません! これは、パフォーマンスが懸念される他のシナリオでは非常に価値があります。

更新: さらに検索して、このタスクの実行方法を説明しているMSDNを見つけました。

私はそれを完全なジェネリック メソッドに変換できるようにしたいと思っていますが、これはリフレクションを使用せずにジェネリックに到達できる限り近いものでした。

public IQueryable<T> TakeAll<T>(QueryOperationResponse<T> qor)
    {
      var collection = new List<T>();
      DataServiceQueryContinuation<T> next = null;
      QueryOperationResponse<T> response = qor;
      do
      {
        if (next != null)
        {
          response = db.Execute<T>(next) as QueryOperationResponse<T>;
        }

        foreach (var elem in response)
        {
          collection.Add(elem);          
        }

      } while ((next = response.GetContinuation()) != null);

      return collection.AsQueryable();
    }

次のように呼び出します:

public IQueryable<ProductColor> GetProductColors()
    {      
      QueryOperationResponse<ProductColor> response = db.ProductColors.Execute() as QueryOperationResponse<ProductColor>;
      var productColors = this.TakeAll<ProductColor>(response);
      return productColors.AsQueryable();
    }
4

2 に答える 2

6

ページングをオフにできない場合は、呼び出しで常に 75 行を受け取ります。次の方法ですべての行を取得できます。

  1. 別のものを追加しIQueryable<ProductColor> AllProductColorsて変更する

    public static void InitializeService(DataServiceConfiguration config)
    {
        config.UseVerboseErrors = true;
        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        config.SetEntitySetPageSize("ProductColors", 75); - Note only paged queries are present
        config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
    
  2. たとえば、必要な数の ProductColors を呼び出す必要があります。

        var cat = new NetflixCatalog(new Uri("http://odata.netflix.com/v1/Catalog/"));
    
        var x = from t in cat.Titles
                where t.ReleaseYear == 2009
                select t;
        var response = (QueryOperationResponse<Title>)((DataServiceQuery<Title>)x).Execute();
    
        while (true)
        {
            foreach (Title title in response)
            {
                Console.WriteLine(title.Name);
            }
    
            var continuation = response.GetContinuation();
            if (continuation == null)
            {
                break;
            }
    
            response = cat.Execute(continuation);
        }
    

次のコードでRxを使用します

public sealed class DataSequence<TEntry> : IObservable<TEntry>
{
    private readonly DataServiceContext context;
    private readonly Logger logger = LogManager.GetCurrentClassLogger();
    private readonly IQueryable<TEntry> query;

    public DataSequence(IQueryable<TEntry> query, DataServiceContext context)
    {
        this.query = query;
        this.context = context;
    }

    public IDisposable Subscribe(IObserver<TEntry> observer)
    {
        QueryOperationResponse<TEntry> response;
        try
        {
            response = (QueryOperationResponse<TEntry>)((DataServiceQuery<TEntry>)query).Execute();
            if (response == null)
            {
                return Disposable.Empty;
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex);
            return Disposable.Empty;
        }
        var initialState = new State
                               {
                                   CanContinue = true,
                                   Response = response
                               };
        IObservable<TEntry> sequence = Observable.Generate(
            initialState,
            state => state.CanContinue,
            MoveToNextState,
            GetCurrentValue,
            Scheduler.ThreadPool).Merge();
        return new CompositeDisposable(initialState, sequence.Subscribe(observer));
    }

    private static IObservable<TEntry> GetCurrentValue(State state)
    {
        if (state.Response == null)
        {
            return Observable.Empty<TEntry>();
        }
        return state.Response.ToObservable();
    }

    private State MoveToNextState(State state)
    {
        DataServiceQueryContinuation<TEntry> continuation = state.Response.GetContinuation();
        if (continuation == null)
        {
            state.CanContinue = false;
            return state;
        }
        QueryOperationResponse<TEntry> response;
        try
        {
            response = context.Execute(continuation);
        }
        catch (Exception)
        {
            state.CanContinue = false;
            return state;
        }
        state.Response = response;
        return state;
    }

    private sealed class State : IDisposable
    {

        public bool CanContinue { get; set; }

        public QueryOperationResponse<TEntry> Response { get; set; }

        public void Dispose()
        {
            CanContinue = false;
        }
    }
}

ODataを介してデータを取得するには、シーケンスを作成し、Rxが残りを行います

 var sequence = new DataSequence<Product>(context.Products, context);
 sequence.OnErrorResumeNext(Observable.Empty<Product>())
            .ObserveOnDispatcher().SubscribeOn(Scheduler.NewThread).Subscribe(AddProduct, logger.Error);
于 2012-07-24T18:42:26.547 に答える
2

ページサイズはサービスの作成者によって設定され、エンティティセットごとに設定できます(ただし、サービスはすべてのエンティティセットに同じページサイズを適用することを選択できます)。クライアントからそれを回避する方法はありません(これはセキュリティ機能であるため、設計によるものです)。

inlinecountオプションは、サーバーに結果の総数(数のみ)を含めるように要求しますが、ページングは​​無効になりません。

クライアントからすべてのデータを読み取る唯一の方法は、最初のページを返す要求を発行することです。これには、次のページを読み取るように要求する次のリンクが含まれている場合があり、最後の応答に次のページがなくなるまで続きます。リンク。

WCF Data Servicesクライアントライブラリを使用している場合は、継続がサポートされており(次のリンク)、簡単なサンプルが次のブログ投稿にあります(例): http: //blogs.msdn.com/b/phaniraj /archive/2010/04/25/server-driven-paging-with-wcf-data-services.aspx

于 2012-07-24T17:55:04.780 に答える