databinding in C# with paging and prefetch paths

Posts   
1  /  2
 
    
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 10-Feb-2009 23:34:55   

ok ... DynamicLists it is! Now ... can you give me a dumbo-proof hint how to do this? Walaa says it's somewhere in these examples: http://www.llblgen.com/pages/files/Example_WebDatabinding_06062008.zip, right? The problem is ... I can't find it ... confused

I also don't want to define the data source and grid view columns in the .aspx file, but in the .cs file. Please correct me if I'm wrong, but for me one of the major benefits of working with LGP is that it shouts and screams upon compile time if something was changed in the database and now can't be found in the VS project.

I think that specifying the data source (entity name etc.) and grid view columns (in particular the names of the datafields, sort expressions etc.) in the .aspx (by name instead by referencing a LGP generated entity from the "library") makes you loose this advantage.

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 11-Feb-2009 09:54:30   

Hi Magic, sorry for the confusion. The example I refered to, was one showing how to bind an entityCollection and access one of its related entity's field. This was done in the aspx code, for example binding a Products collection, if you want to display the CategoryName from the related Category entity, you would do something like:

                        <asp:TemplateField HeaderText="Category" SortExpression="CategoryId">
                            <ItemTemplate>
                                <asp:Label ID="Category" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Category.CategoryName")%>' />
                            </ItemTemplate>
                            <EditItemTemplate>
                                <asp:DropDownList ID="Categories" runat="server" DataSourceID="CategoriesDS" DataTextField="CategoryName"
                                    DataValueField="CategoryId" SelectedValue='<%# Bind("CategoryId") %>' />
                            </EditItemTemplate>
                        </asp:TemplateField>

The edit template is just a bonus tip simple_smile

Now if you want to avoid aspx code, then simply try to mimic this in code, or the original way is to use the RowDataBound event to display what you need, where you can digg deep in the related entities and pick any field you like to be displayed.

That's if you still want to use the entityCollection approach. But your case seems a lot different:

What I'm trying to achieve is a completely "dynamic" data source for a grid view. Basically basing a GridView on a db view without having to really create a view in the database.

So for example ... I start out with the OrderEntity (to stick to your example). If I want a GridView that shows more details about the CustomerEntity, I "join in" the customer. If I want to have more details about the product ordered, I "join in" the ProductEntity, or maybe also the "ProductCategory" entity.

I might need such views depending on how I look at the order, from a "customer's perspective", or from a "product's perspective" etc.

Reading the above analysis I say you should use a DynamicList, where you can dynamically add fields and join to tables/entities.

Then comes the databinding part, which is required to be done in code not in aspx, so now you have constructed and fetched a dataTable, and the ball is your now to try to display it in a GridView or anything else.

magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 11-Feb-2009 16:16:04   

MTrinder, Walaa, thanks a lot for the help! I think I have finally figured out the idea with the DataTable completely! simple_smile

Unfortunately, I already have the next question: Since the DataTable does not have any sorting capabilities (the Grid is sortable, so I need to delegate the sorting requests to the DataTable), I think that I shouldn't use the DataTable as the grid's DataSource directly.

My idea is to create a DataView based on the dynamically created DataTable and bind this DataView to the DataSource of the GridView. This way I can delegate sorting requests of the GridView to the DataTable through the DataView.Sort property.

Any thoughts on this?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 11-Feb-2009 16:22:51   

If you want to search at the database side, you will find overloads of the method which fetches the DynamicList, which accepts a sortExpression, so you can just capture the GridView's sortExpression and then re-run the fetch method to fetch based on the specified sortExpression.

magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 11-Feb-2009 22:55:47   

Walaa wrote:

If you want to search at the database side, you will find overloads of the method which fetches the DynamicList, which accepts a sortExpression, so you can just capture the GridView's sortExpression and then re-run the fetch method to fetch based on the specified sortExpression.

By "which fetches the DynamicList", you mean the adapter.FetchTypedList() method, right?

I basically have implemented the functionality that I was aiming at, there is only one small flaw: When I call the constructor of my DynamicList class (extends System.Data.DataView), I fetch (execute adapter.FetchTypedList()) once and then when I (possibly) reset the sort expression because of a sorting event of the GridView, I fetch the data again.


abstract public class DynamicList : DataView
{

    private IEntityFields2 _fields = null;
    private SortSetup _sortSetup = null;
    
    public DynamicList()
        :
        base()
    {
        // set the table to the given name
        base.Table = new DataTable(getTableName());

        // store the given fields and the given sort setup
        this._fields = getFields();
        this.SortSetup = getStandardSort();
    }

    public SortSetup SortSetup
    {
        get
        {
            return this._sortSetup;
        }
        set
        {
            // store the value
            this._sortSetup = value;

            // set the sort expression of the dataview
            if (this._sortSetup != null)
            {
                this.Sort = _sortSetup.FullExpression;
            }
            else
            {
                this.Sort = null;
            }

            // fetch the data
            fetchData();
        }
    }

    protected void fetchData()
    {
        // get the sortExpression from the given setup
        ISortExpression sortExpression = null;
        if (this.SortSetup != null)
        {
            sortExpression = this.SortSetup.getSortExpression(this._fields);
        }

        // clear the contents of the data table
        this.Table.Clear();

        // fill the dataTable using the DataAccessAdapter
        DataAccessAdapter adapter = new DataAccessAdapter();
        adapter.FetchTypedList(_fields, this.Table, getFilter(), 0, sortExpression,
            allowDuplicates(), getGroupByClause());
    }

    abstract protected string getTableName();
    abstract protected IEntityFields2 getFields();
    abstract protected SortSetup getStandardSort();

    protected virtual bool allowDuplicates()
    {
        return true;
    }

    protected virtual IRelationPredicateBucket getFilter()
    {
        return null;
    }

    protected virtual IGroupByCollection getGroupByClause()
    {
        return null;
    }
}

I was trying to find out how the DataView "could know" that it is about to be bound to the GridView and fetch the only once (just before the GridView wants to access it). Unfortunately there doesn't seem to be any event handler that I could override.

Is there a way to extend the DataView functionality to capture the DataBinding event of the GridView? There is a method LLBLGenProDataSource2.OnDataBinding() ... so should rather find a way how to set the dynamically created DataTable as ... for example the EntityCollection of the LLBLGenProDataSource2 let's say by extending the LLBLGenProDataSource2 class and then use its functionality/methods?

I know I could write a method to fetch the data and call it from the GridView when OnDataBinding method is executed. I just think it would "nicer" to have this functionality implemented on the DynamicList side.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 12-Feb-2009 06:03:00   

The problem here is that DynamicLists are dynamic, so there's no certainty of what they will contain. LLBLGenProDataSource2 work with factories, so I think it would be tricky to adapt that to your dynamic lists.

I would use the handlers provided by GridView (Sorting event handler) and then see whether the data is already fecthed, if so then filter on-memory (using DataViews).

Or (and this maybe doesn't like you, coz your current work on DynamicLists) use TypedViews (DB views mapped to your model) as they are supported by the LLBLGenProDataSource2.

David Elizondo | LLBLGen Support Team
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 13-Feb-2009 14:53:34   

daelmo wrote:

The problem here is that DynamicLists are dynamic, so there's no certainty of what they will contain. LLBLGenProDataSource2 work with factories, so I think it would be tricky to adapt that to your dynamic lists.

hmmm ... I thought I might be able to trick the LGP data source into just accepting an EntityCollection that I would generate from the DynamicList ...

daelmo wrote:

I would use the handlers provided by GridView (Sorting event handler) and then see whether the data is already fecthed, if so then filter on-memory (using DataViews).

can you think of a method/property that indicates whether data was already fetched? I couldn't find one so far, so I guess, I have to write this on my own ...

daelmo wrote:

Or (and this maybe doesn't like you, coz your current work on DynamicLists) use TypedViews (DB views mapped to your model) as they are supported by the LLBLGenProDataSource2.

the DynamicLists have other benefits for me (as we discussed here http://llblgen.com/TinyForum/Messages.aspx?ThreadID=14983) so I want to use them (at least in a major part of the cases).

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 16-Feb-2009 10:22:51   

can you think of a method/property that indicates whether data was already fetched? I couldn't find one so far, so I guess, I have to write this on my own ...

If the Grid View has Rows (count > 0), then data must have been fetched.

1  /  2