0

SPGridView(GridViewに基づくSharePointコントロール)でObjectDataSourceを使用しており、ログを見ると、SelectMethodが9回呼び出されています。これは、実際に必要な回数の8倍です。

ObjectDataSourceオブジェクトがSelectメソッドを呼び出す条件、またはチェックする項目の大きなリスト/これを最適化するための提案を誰かが正確に知っているかどうか疑問に思いましたか?それはDataBoundなので、それはすべてSPGridViewにかかっているということですか?

selectcountmethodが(このSOの回答に従って)一度呼び出すことは知っていますが、なぜselectメソッドを何度も呼び出す必要があるのか​​よくわかりません。私は間違ったステップで拘束していますか?間違ったステップで初期化していますか?また、ページング、並べ替え、フィルタリングを有効にしています...どんなヒントでも素晴らしいでしょう:)

編集:イベントにログコードを追加しましたが、GridViewのDataBindingイベントが複数回ヒットしているようです。つまり、内部的にSPGridViewがDataBind()を複数回呼び出しているということですか?私が呼び出す唯一のDataBind()は、ユーザーコントロールのRenderイベントであり、これは1回だけ発生します。

ロギングトレース:

ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
...
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
....
GridView_RowDataBound
ODS_Selecting
ODS_ObjCreating
ODS_Selecting
Gridview_DataBinding
GridView_RowDataBound
....
GridView_RowDataBound

また、ここにコードの大きな塊があります!

.ascx:

<SharePoint:SPGridView ID="appGridView" DataSourceID="appODS" AutoGenerateColumns="false" 
AllowPaging="true" PageSize="10" AllowSorting="true"
AllowFiltering="true" FilterDataFields=",,,,TimeElapsed,,," FilteredDataSourcePropertyName="FilterExpression" FilteredDataSourcePropertyFormat="{1} = '{0}'"
runat="server" />
<wc:ObjectDataSource ID="appODS" runat="server" />
<SharePoint:SPGridViewPager ID="appGridViewPager" runat="server" GridViewId="appGridView" />

.ascx.cs:

パブリック部分クラスMyUserControl:UserControl {

    //http://www.reversealchemy.net/blog/2009/05/01/building-a-spgridview-control-part-1-introducing-the-spgridview/
    //http://www.reversealchemy.net/2009/05/24/building-a-spgridview-control-part-2-filtering/

    protected override void OnInit(EventArgs e)
    {
        appODS.EnablePaging = true;
        appODS.SelectMethod = "GetMyDataTable";
        appODS.SelectCountMethod = "GetMyDataTableCount";
        appODS.StartRowIndexParameterName = "rowStart";
        appODS.MaximumRowsParameterName = "rowCount";

        appODS.SelectParameters.Add(new Parameter { Name = "myParam", DefaultValue = "test" });  
        appODS.TypeName = this.GetType().AssemblyQualifiedName;
        appODS.ObjectCreating += new ObjectDataSourceObjectEventHandler(appODS_ObjectCreating);

        appGridView.RowDataBound += new GridViewRowEventHandler(appGridView_RowDataBound);
        appODS.Filtering += new ObjectDataSourceFilteringEventHandler(appODS_Filtering);
        appGridView.Sorting += new GridViewSortEventHandler(appGridView_Sorting);
    }


    //https://stackoverflow.com/questions/1351578/spgridview-data-and-correct-method-of-ensuring-data-is-safe
    protected override void OnPreRender(EventArgs e)
    {
        if (!string.IsNullOrEmpty(appODS.FilterExpression))
        {
            appODS.FilterExpression = string.Format(
                appGridView.FilteredDataSourcePropertyFormat,
                appGridView.FilterFieldValue.Replace("'", "''"),
                appGridView.FilterFieldName
                );
        }

        base.OnPreRender(e);
    }


    private void appODS_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
    {
        e.ObjectInstance = this;
    }

    protected sealed override void Render(HtmlTextWriter writer)
    {
        GenerateColumns();
        appGridView.DataBind();
        base.Render(writer);
    }

    public DataTable GetMyDataTable(string myParam, int rowStart, int rowCount)
    {
        DataTable dt = new DataTable();

        dt.Columns.Add("ID", typeof(Int32));
        // more columns here 
        dt.Columns.Add("TestColumn", typeof(decimal));


        List<Stuff> things = svc.GetStuff();


        foreach (Stuff thing in things)
        {
            dt.Rows.Add(
                thing.Blah, thing.Blah2);
        }

        return dt;
    }

    public int GetMyDataTableCount(string myParam)
    {
        return 10003; //faked out for now           
    }

    private void GenerateColumns()
    {
        BoundField column = new BoundField();
        column.DataField = "ID";
        column.SortExpression = "ID";
        column.HeaderText = "ID";            
        appGridView.Columns.Add(column);

        //more

        column = new BoundField();
        column.DataField = "TestColumn";
        column.SortExpression = "TestColumn";
        column.HeaderText = "TestColumn";
        appGridView.Columns.Add(column);

    }


    ////filtering
    protected sealed override void LoadViewState(object savedState)
    {
        base.LoadViewState(savedState);

        if (Context.Request.Form["__EVENTARGUMENT"] != null &&
             Context.Request.Form["__EVENTARGUMENT"].EndsWith("__ClearFilter__"))
        {
            // Clear FilterExpression
            ViewState.Remove("FilterExpression");
        }
    }

    private void appODS_Filtering(object sender, ObjectDataSourceFilteringEventArgs e)
    {
        ViewState["FilterExpression"] = ((ObjectDataSourceView)sender).FilterExpression;
    }

    private void appGridView_Sorting(object sender, GridViewSortEventArgs e)
    {
        if (ViewState["FilterExpression"] != null)
        {
            appODS.FilterExpression = (string)ViewState["FilterExpression"];
        }
    }

    private void appGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (sender == null || e.Row.RowType != DataControlRowType.Header)
        {
            return;
        }

        SPGridView grid = sender as SPGridView;

        if (String.IsNullOrEmpty(grid.FilterFieldName))
        {
            return;
        }

        // Show icon on filtered column
        for (int i = 0; i < grid.Columns.Count; i++)
        {
            DataControlField field = grid.Columns[i];

            if (field.SortExpression == grid.FilterFieldName)
            {
                Image filterIcon = new Image();
                filterIcon.ImageUrl = "/_layouts/images/filter.gif";
                filterIcon.Style[HtmlTextWriterStyle.MarginLeft] = "2px";

                // If we simply add the image to the header cell it will
                // be placed in front of the title, which is not how it
                // looks in standard SharePoint. We fix this by the code
                // below.
                Literal headerText = new Literal();
                headerText.Text = field.HeaderText;

                PlaceHolder panel = new PlaceHolder();
                panel.Controls.Add(headerText);
                panel.Controls.Add(filterIcon);

                e.Row.Cells[i].Controls[0].Controls.Add(panel);

                break;
            }
        }
    }
}
4

1 に答える 1

0

最終的には、リフレクターを作成してもう少し掘り下げて解決しました。SPGridViewはBaseDataBoundControlを継承しているため、Renderメソッドで.DataBind()呼び出しも必要ないことがわかりました。これにより、必要に応じてDataBindが呼び出されます。 --MSDNで理解していることから、OnPreRenderと呼ばれます。

Renderイベント(appGridView.Columns.Add(column);)で列を生成することにより、appGridViewを変更するたびに、DataBind()メソッドが再度呼び出されることになりました。そのため、Renderイベントは遅すぎます。グリッドビュー列を設定するために、その段階までにすべてがすでに完了していることを期待しており、新しい列を追加するたびに、データを取得するために「再バインド」する必要がありました。

これは大規模なパフォーマンスの問題であり、ObjectDataSourceを使用してSPGridViewを設定する方法について、他の点では適切な例に従っている場合に注意する必要があります。

于 2012-09-07T02:15:04.840 に答える