Strange Paging Problem

Posts   
 
    
Posts: 37
Joined: 21-Oct-2004
# Posted on: 30-May-2008 22:12:00   

Hi,

We're seeing a strange paging problem when combining an LLBLGenDataSource (self-servicing) with a Telerik RadGrid. Here's the situation:

  1. The RadGrid and the DataSource play great together on every operation - Sorting, Filtering, AJAX updates, etc.
  2. Paging is enabled on both objects, LivePersistance is enabled on the Data Source.
  3. Page Size is 4, there are 7 records to retrieve.
  4. We're setting a FilterToUse on the DataSource during PageLoad.
  5. We're using an Oracle 10g backend (the latest ODP.NET driver)

If we try to change the page on the grid, we a "Value does not fall within the expected range." from th Oracle.DataAccess namespace, like so:


Oracle.DataAccess.Client.OracleParameter.set_Value(Object value)
   at SD.LLBLGen.Pro.DQE.Oracle.OracleSpecificCreator.CreateParameter(IEntityFieldCore field, IFieldPersistenceInfo persistenceInfo, ParameterDirection direction, Object valueToSet)

Now, what's really strange is that if we remove the FilterToUse, the paging works just fine. Here's the relevant code:

ASP Page


<llblgenpro:LLBLGenProDataSource ID="orgsDs" runat="server" 
    DataContainerType="EntityCollection" 
EntityCollectionTypeName="DataAccess.CollectionClasses.OrganizationCollection, DataAccess"
    enablePaging="true"
    LivePersistence="true"  />
    
<telerik:RadGrid ID="OrganizationList" runat="server" 
    StatusBarSettings-LoadingText="Loading Data..." ShowStatusBar="true"
    DataSourceID="orgsDs" 
    PageSize="4"
    AllowPaging="true" 
    AllowCustomPaging="true"
    PagerStyle-Mode="Slider" 
    AllowSorting="true">
    <MasterTableView AutoGenerateColumns="false" TableLayout="Auto" DataKeyNames="Id" AllowPaging="true" PageSize="4">
        <Columns>
            <telerik:GridHyperLinkColumn DataTextField="Name" HeaderText="Name" SortExpression="Name" DataNavigateUrlFormatString="OrganizationEdit.aspx?id={0}" DataNavigateUrlFields="Id" />
            <telerik:GridBoundColumn DataField="Description" HeaderText="Description"  />
            <telerik:GridBoundColumn DataField="IsEnabled" DataType="System.Boolean" HeaderText="Enabled" UniqueName="EnabledCol" />
            <telerik:GridDateTimeColumn DataField="Created" HeaderText="Date Created" />
            <telerik:GridDateTimeColumn DataField="Modified" HeaderText="Date Modified" />
            <telerik:GridTemplateColumn HeaderText="Actions" UniqueName="ActionsCol">
                <ItemTemplate>
                    <asp:Button ID="DeleteButton" runat="server" Text="Delete" OnCommand="DeleteClick" CommandArgument='<%# Eval("Id") %>' />
                </ItemTemplate>
            </telerik:GridTemplateColumn>
        </Columns>
    </MasterTableView>
    </telerik:RadGrid>

.cs CodeBehind


 protected void Page_Load(object sender, EventArgs e)
    {
        orgsDs.FilterToUse = new PredicateExpression(OrganizationFields.IsDeleted == false);
    }

Any ideas on why setting the FilterToUse property would screw up paging, but not anything else?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 31-May-2008 04:13:43   

Hi there,

Please let us know these things:

David Elizondo | LLBLGen Support Team
Posts: 37
Joined: 21-Oct-2004
# Posted on: 05-Jun-2008 02:10:30   

We're using LLBLGenPro 2.5 ODP.NET 2.102.2.20 DB Type of IsDeleted is a Number(1) We use a custom Guid convertor for any primary keys.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 05-Jun-2008 10:24:47   

Please post the LLBLGen Pro Runtime Libraries version (http://llblgen.com/TinyForum/Messages.aspx?ThreadID=7720)

Thanks.

Posts: 37
Joined: 21-Oct-2004
# Posted on: 05-Jun-2008 17:08:10   

My apologies:

SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll: 2.5.8.228

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 06-Jun-2008 11:44:38   

Are you using a TypeConverter on this field?

What happens if you use another field instead of IsDeleted in the filter?

orgsDs.FilterToUse = new PredicateExpression(OrganizationFields.AnotherField == xyz);
Posts: 37
Joined: 21-Oct-2004
# Posted on: 09-Jun-2008 22:00:48   

If I use a date field, it works just fine. FYI - we're using the standard LLBLGen BooleanNumericConvertor with a Number(1,0) in the Oracle database.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 10-Jun-2008 09:43:09   

The error you see "Value does not fall within the expected range" is a generic error from ODP.NET which illustrates that the value set doesn't match the type of the parameter.

What I'd like to know is: if you do: OrganizationCollection orgs = new OrganizationCollection(); orgs.GetMulti(OrganizationFields.IsDeleted==false);

is that working properly? Also if you fetch page 2 ? Because it looks like the error is occuring during the parameter creation for the filter.

You didn't show the whole stacktrace, which might have been more helpful in this, but anyway, the datasourcecontrol executes similar code so the problem should pop up with the code above as well. Please include full stacktraces as well simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 14-Jun-2008 01:09:37   

Sorry for the delay, I was on the road.

We have 6 organizations in our database right now. Paging with the GetMulti function appears to work just fine:


OrganizationCollection orgs = new OrganizationCollection();
        PredicateExpression pred = new PredicateExpression(OrganizationFields.IsDeleted == false);
        orgs.GetMulti(pred, 0, null, null, 2, 4);
        Response.Write("Found : " + orgs.Count.ToString() + " organizations!");

Results in: Found : 2 organizations!


OrganizationCollection orgs = new OrganizationCollection();
        PredicateExpression pred = new PredicateExpression(OrganizationFields.IsDeleted == false);
        orgs.GetMulti(pred);
        Response.Write("Found : " + orgs.Count.ToString() + " organizations!");

Results in: **Found : 6 organizations! **

Here's the stack trace from an error:


 at Oracle.DataAccess.Client.OracleParameter.set_Value(Object value)
   at SD.LLBLGen.Pro.DQE.Oracle.OracleSpecificCreator.CreateParameter(IEntityFieldCore field, IFieldPersistenceInfo persistenceInfo, ParameterDirection direction, Object valueToSet)
   at SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareValuePredicate.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker, Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Int32& uniqueMarker)
   at SD.LLBLGen.Pro.DQE.Oracle.DynamicQueryEngine.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Boolean relationsSpecified, Boolean sortClausesSpecified)
   at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateRowCountDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse, IPredicate selectFilter, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.GetDbCount(IEntityFields fields, ITransaction containingTransaction, IPredicate filter, IRelationCollection relations, IGroupByCollection groupByClause, Boolean allowDuplicates)
   at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.GetDbCount(IEntityFields fields, ITransaction containingTransaction, IPredicate filter, IRelationCollection relations, IGroupByCollection groupByClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase`1.GetDbCount(IPredicate filter, IRelationCollection relations)
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase`1.SD.LLBLGen.Pro.ORMSupportClasses.IEntityCollection.GetDbCount(IPredicate filter, IRelationCollection relations)
   at SD.LLBLGen.Pro.ORMSupportClasses.LLBLGenProDataSourceView.ExecuteSelectEntityCollection(Int32 pageSize, Int32 pageNumber, DataSourceSelectArguments arguments)
   at SD.LLBLGen.Pro.ORMSupportClasses.LLBLGenProDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)
   at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
   at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
   at Telerik.Web.UI.GridTableView.PerformSelect()
   at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
   at Telerik.Web.UI.GridTableView.DataBind()
   at Telerik.Web.UI.GridPageChangedEventArgs.ExecuteCommand(Object source)
   at Telerik.Web.UI.GridPagerItem.slider_ValueChanged(Object sender, EventArgs e)
   at Telerik.Web.UI.RadSlider.OnValueChanged(EventArgs e)
   at Telerik.Web.UI.RadSlider.LoadClientState(Dictionary`2 clientState)
   at Telerik.Web.UI.RadWebControl.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at Telerik.Web.UI.RadWebControl.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Does this help?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 15-Jun-2008 11:53:25   

The datasource control also calls the same GetMulti() routine, so it's strange that it causes an exception there but not in normal code...

The type converters are used automatically in this situation, so it's not a matter of 'the datasource control doesn't set the type converters', these are obtained from the field used.

Could you switch off livepersistence and implement the PerformSelect() and PerformDbCount routines (just use simple code which simply does a GetMulti call) so you can set a breakpoint there and examine what exactly is send as the predicate? The error is with the predicate, so I'd like to see what exactly is passed as value in the compare value predicate.

See for examples of how to implement the event handlers, the example in "Using the generated code -> SelfServicing -> Databinding with ASP.NET 2.0 -> Usage examples.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 18-Jun-2008 06:24:37   

Okay, I did this and was able to set a breakpoint. Now, I'm not sure I'm looking at exactly the right information, since clicking the little plus signs in the Locals window can get a little deep with Predicates, but it appears as though the TypeConvertor isn't getting picked up on the PostBack for some reason. In the initial Page request, TypeConvertorToUse is set correctly on the Predicate's Field value (this is about 3 or 4 levels deep in the Locals window), and on the Postback it's set to null. I imagine that could have something to do with this problem, but I've got no way to know what's causing it.

Any ideas? Is there any way that I can give you additional information now that I've at least got a recreatable breakpoint?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 18-Jun-2008 11:16:22   

I could reproduce the behavior you're seeing:


[Test]
public void DeserializationOfPredicateWithTypeConverterContainingFieldTest()
{
    FieldCompareValuePredicate filter = new FieldCompareValuePredicate(ProductFields.ReorderLevel, ComparisonOperator.Equal, true);
    Assert.IsNotNull(filter.Field.TypeConverterToUse);
    BinaryFormatter formatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream();
    formatter.Serialize(stream, filter);
    stream.Seek(0, SeekOrigin.Begin);
    FieldCompareValuePredicate dFilter = (FieldCompareValuePredicate)formatter.Deserialize(stream);
    stream.Close();
    Assert.IsNotNull(dFilter.Field.TypeConverterToUse);
}

Fails at the last line. Will look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 18-Jun-2008 11:26:18   

The problem is that the type converter instance isn't made serializable in the FieldPersistenceInfo object, which is inside the entityfield.

The main reason is that it's not defined if the typeconverter is serializable (as it's custom code), so we don't serialize it with the data. Normally you won't run into this, as an entity which is deserialized, it's re-creating its fields, so it gets this object properly inserted. However in the situation where a predicate is serialized, it's a different story, as it contains a field, and this field isn't re-created during deserialization but simply deserialized.

The sad part is that 'TypeConverter' isn't a serializable type. So the TypeConverter instances can't be serialized. So I'll add some code which re-creates the TypeConverter instance at deserialization time (if possible).

(edit) I fixed it. Please see the attached ORMSupportClasses for the fix.

(also present in v2.6 btw)

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 18-Jun-2008 18:14:41   

That did it! We're paging like mad now!

Thanks much Frans! It's great to work with a tool where you can actually get reliable, immediate support from the vendor / creator. Can't wait to upgrade to 2.6 too - the ability to do inline views is going to be huge for us. When do you think a maintenance release with this fix will be out?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 18-Jun-2008 18:18:59   

ConfluentData wrote:

That did it! We're paging like mad now!

Thanks much Frans! It's great to work with a tool where you can actually get reliable, immediate support from the vendor / creator. Can't wait to upgrade to 2.6 too - the ability to do inline views is going to be huge for us. When do you think a maintenance release with this fix will be out?

Tomorrow (thursday) for v2.6 and v2.5, as in v2.6 there's still 1 bug left to finish simple_smile For v2.5 you can keep on using this build, it's a release RTM build so it's the same as the one we'll shipping tomorrow.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 18-Jun-2008 18:20:48   

Awesome, thanks again Frans!