2

ASP.Net Async ページに関する次のブログを読んでいました。

そして、私の頭に疑問が浮かびました。次のシナリオを考えてください。

  1. 非同期ページの想定
  2. このページは、ASP.Net 作業スレッドをすぐに解放してスケーラビリティを高めるために、データベースからデータを取得するための非同期操作を登録します。
  3. ページは、ページング情報をこれらの操作に渡して、データベース サーバーでページ付けします。
  4. 操作が完了し、正しいデリゲートが新しいスレッドで呼び出されます。(ASP.Net スレッド プールのスレッドを使用しない)
  5. GridViewデータはページに返され、上のコントロールにバインドできます。Page_PreRendercomplete

この時点で、ページにページングされたデータをバインドしてユーザーに表示する準備ができました(表示する必要があるレコードとVirtual Rows Count の数のみを返します) 。

したがって、この情報を使用して、コントロールにバインドしたいと思いますが、ページング結果をGridView自分のコントロールに表示する方法がわかりませんGridView

次のコードを使用してみました:

protected override void OnPreRenderComplete(EventArgs e)
{
    if (this.shouldRefresh)
    {
        var pagedSource = new PagedDataSource
        {
            DataSource = this.Jobs, 
            AllowPaging = true,
            AllowCustomPaging = false,
            AllowServerPaging = true,
            PageSize = 3,
            CurrentPageIndex = 0,
            VirtualCount = 20
        };

        this.gv.DataSource = pagedSource;
        this.gv.DataBind();
    }

    base.OnPreRenderComplete(e);
}

しかし、GridViewコントロールは単にVirtualCountプロパティを無視し、ページャーは表示されません。これは私が得たものです:

ここに画像の説明を入力

ASPX

<%@ Page Async="true" AsyncTimeout="30"  ....
...
    <asp:GridView runat="server" ID="gv" DataKeyNames="job_id" 
        AllowPaging="true" PageSize="3"
    >
        <Columns>
            <asp:CommandField ShowSelectButton="true" />
        </Columns>
        <SelectedRowStyle Font-Bold="true" />
    </asp:GridView>

ASPX コードビハインド

protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        this.shouldRefresh = true;
    }
}

public IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback callback, object state)
{
    var operation = new MyClassResult(callback, Context, state);
    operation.StartAsync();
    return operation;
}

public void EndAsyncOperation(IAsyncResult result)
{
    var operation = result as MyClassResult;
    this.Jobs = operation.Jobs;
}

ノート:

  • データを取得するためにサーバーへのjQuery非同期投稿には興味がありません

  • MyClassResultIAsyncResultデータベースサーバーからのデータを実装して返す

  • ObjectDataSource可能であれば使用したい

4

1 に答える 1

2

少なくともさらなる探求の良い出発点になり得るものがあると思います。いくつかのアイデアに基づいた方法を説明するために、サンプルを作成しました(さらに下に)。

  1. ページングを機能させるには、ObjectDatasourceを使用する必要があります。そうGridViewすれば、合計で何行あるかを知ることができます。
  2. ObjectDataSourceフェッチしたデータが利用可能になったら、そのデータにアクセスできるようにする方法が必要です。

2. を解決するために思いついたアイデアは、GridViewが配置されているページが実装できるインターフェイスを定義することでした。次に、ObjectDataSourceデータを取得するための呼び出しをページ自体に中継するクラスを使用できます。呼び出しが早すぎると、空のデータが返されますが、後で実際のデータに置き換えられます。

いくつかのコードを見てみましょう。

これが私のaspxファイルです:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="GridViewTest.aspx.cs" Inherits="GridViewTest" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="Server">
    <asp:GridView ID="jobsGv" runat="server" AutoGenerateColumns="false" AllowPaging="true"
        PageSize="13" OnPageIndexChanging="jobsGv_PageIndexChanging" DataSourceID="jobsDataSource">
        <Columns>
            <asp:TemplateField HeaderText="Job Id">
                <ItemTemplate>
                    <asp:Literal ID="JobId" runat="server" Text='<%# Eval("JobId") %>'></asp:Literal>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Job description">
                <ItemTemplate>
                    <asp:Literal ID="Description" runat="server" Text='<%# Eval("Description") %>'></asp:Literal>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Min level">
                <ItemTemplate>
                    <asp:Literal ID="MinLvl" runat="server" Text='<%# Eval("MinLvl") %>'></asp:Literal>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
    <asp:ObjectDataSource ID="jobsDataSource" runat="server" TypeName="JobObjectDs" CacheDuration="0"
        SelectMethod="GetJobs" EnablePaging="True" SelectCountMethod="GetTotalJobsCount">
    </asp:ObjectDataSource>
    <asp:Button ID="button" runat="server" OnClick="button_Click" Text="Test postback" />
</asp:Content>

そして背後にあるコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;

public partial class GridViewTest : System.Web.UI.Page, IJobDsPage
{
    bool gridNeedsBinding = false;
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            gridNeedsBinding = true;
        }
    }
    protected void jobsGv_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        var gv = (GridView)sender;
        newPageIndexForGv = e.NewPageIndex;
        gridNeedsBinding = true;
    }
    private int newPageIndexForGv = 0;
    protected void Page_PreRendercomplete(object sender, EventArgs e)
    {
        if (gridNeedsBinding)
        {
            // fetch data into this.jobs and this.totalJobsCount to simulate 
            // that data has just become available asynchronously
            JobDal dal = new JobDal();
            jobs = dal.GetJobs(jobsGv.PageSize, jobsGv.PageSize * newPageIndexForGv).ToList();
            totalJobsCount = dal.GetTotalJobsCount();

            //now that data is available, bind gridview
            jobsGv.DataBind();
            jobsGv.SetPageIndex(newPageIndexForGv);
        }
    }

    #region JobDsPage Members

    List<Job> jobs = new List<Job>();
    public IEnumerable<Job> GetJobs()
    {
        return jobs;
    }
    public IEnumerable<Job> GetJobs(int maximumRows, int startRowIndex)
    {
        return jobs;
    }
    int totalJobsCount;
    public int GetTotalJobsCount()
    {
        return totalJobsCount;
    }

    #endregion

    protected void button_Click(object sender, EventArgs e)
    {
    }
}

そして最後に、それを結び付けるいくつかのクラスがあります。これらを App_Code の 1 つのコード ファイルにまとめました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Simple POCO to use as row data in GridView
/// </summary>
public class Job
{
    public int JobId { get; set; }
    public string Description { get; set; }
    public int MinLvl { get; set; }
    //etc
}

/// <summary>
/// This will simulate a DAL that fetches data
/// </summary>
public class JobDal
{
    private static int totalCount = 50; // let's pretend that db has total of 50 job records
    public IEnumerable<Job> GetJobs()
    {
        return Enumerable.Range(0, totalCount).Select(i => 
            new Job() { JobId = i, Description = "Descr " + i, MinLvl = i % 10 }); //simulate getting all records
    }
    public IEnumerable<Job> GetJobs(int maximumRows, int startRowIndex)
    {
        int count = (startRowIndex + maximumRows) > totalCount ? totalCount - startRowIndex : maximumRows;
        return Enumerable.Range(startRowIndex, count).Select(i => 
            new Job() { JobId = i, Description = "Descr " + i, MinLvl = i % 10 }); //simulate getting one page of records
    }
    public int GetTotalJobsCount()
    {
        return totalCount; // simulate counting total amount of rows
    }
}

/// <summary>
/// Interface for our page, so we can call methods in the page itself
/// </summary>
public interface IJobDsPage
{
    IEnumerable<Job> GetJobs();
    IEnumerable<Job> GetJobs(int maximumRows, int startRowIndex);
    int GetTotalJobsCount();
}

/// <summary>
/// This will be used by our ObjectDataSource
/// </summary>
public class JobObjectDs
{
    public IEnumerable<Job> GetJobs()
    {
        var currentPageAsIJobDsPage = (IJobDsPage)HttpContext.Current.CurrentHandler;
        return currentPageAsIJobDsPage.GetJobs();
    }
    public IEnumerable<Job> GetJobs(int maximumRows, int startRowIndex)
    {
        var currentPageAsIJobDsPage = (IJobDsPage)HttpContext.Current.CurrentHandler;
        return currentPageAsIJobDsPage.GetJobs(maximumRows, startRowIndex);
    }
    public int GetTotalJobsCount()
    {
        var currentPageAsIJobDsPage = (IJobDsPage)HttpContext.Current.CurrentHandler;
        return currentPageAsIJobDsPage.GetTotalJobsCount();
    }
}

それで、それはすべて何をしますか?

さて、IJobDsPageインターフェイスを実装している Page があります。ページには、 with idGridViewを使用している があります。つまり、クラスを使用してデータをフェッチします。そして、そのクラスは、現在実行中の Page を から取得し、それをインターフェイスにキャストして、Page のインターフェイス メソッドを呼び出します。ObjectDataSourcejobsDataSourceJobObjectDsHttpContextIJobDsPage

その結果、データを取得するためにページ内のメソッドを呼び出すGridViewを使用するが得られます。ObjectDataSourceこれらのメソッドの呼び出しが早すぎると、空のデータが返されます (new List<Job>()対応する合計行数が 0 になります)。ただし、データが利用可能なページ処理の段階に達したときに GridView を手動でバインドしているため、これは問題ありません。

全体として、私のサンプルはうまくいきますが、素晴らしいとは言えません。現状では、はリクエスト中に関連付けられたメソッドを複数回ObjectDataSource呼び出します。ただし、実際のデータの取得は 1 回しか行われないSelectため、最初に思ったほど悪くはありません。また、次のページに遷移するときに同じデータに 2 回バインドされます。GridView

そのため、改善の余地があります。しかし、それは少なくとも出発点です。

于 2012-08-21T20:29:26.400 に答える