LLBLGenProDataSource2 Bug

Posts   
 
    
deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 30-Nov-2006 20:15:28   

The easiest way for me to describe this bug is with code:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Copy of Test.aspx.cs" Inherits="Test_Test" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses.NET20" Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="llblgenpro" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <llblgenpro:LLBLGenProDataSource2 ID="CustomerDataSource" runat="server" AdapterTypeName="Data.DatabaseSpecific.DataAccessAdapter, DataDBSpecific"
            DataContainerType="EntityCollection" EntityFactoryTypeName="Data.FactoryClasses.CustomerEntityFactory, Data">
        </llblgenpro:LLBLGenProDataSource2>
        <llblgenpro:LLBLGenProDataSource2 ID="OrderDataSource" runat="server" AdapterTypeName="Data.DatabaseSpecific.DataAccessAdapter, DataDBSpecific"
            DataContainerType="EntityCollection" EntityFactoryTypeName="Data.FactoryClasses.OrderEntityFactory, Data">
            <SelectParameters>
                <asp:ControlParameter ControlID="CustomerDropDownList" Name="CustomerId" PropertyName="SelectedValue" />
            </SelectParameters>
        </llblgenpro:LLBLGenProDataSource2>
        &nbsp;&nbsp;
        <br />
        <asp:DropDownList ID="CustomerDropDownList" runat="server" AutoPostBack="True" DataSourceID="CustomerDataSource"
            DataTextField="CustomerId" DataValueField="CustomerId">
        </asp:DropDownList>
        <asp:DropDownList ID="OrderDropDownList" runat="server" DataSourceID="OrderDataSource"
            DataTextField="OrderId" DataValueField="OrderId" AutoPostBack="True">
        </asp:DropDownList>
        &nbsp;&nbsp;<br />
    
    </div>
    </form>
</body>
</html>

Now whenever you click on the second DropDownList it postbacks, but the SelectedIndex is always reset. This is somehow related to the SelectParameter of OrderDataSource. Also if I hardcode the value of the parameter (instead of taking it from the CustomerDropDownList) the SelectedIndex is preserved.

I've tested the same scenario with SqlDataSource and it works fine. The SelectedIndex is preserved.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 01-Dec-2006 08:29:43   

What's in the codebehind of the second dropdownlist selectedIndexChanged (when it post back)?

What's the runtime library version you are using? (Refer to the following thread for info about how to get it: http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=7717)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 08:54:18   

PLease download the latest runtimes, this was fixed some time ago.

Frans Bouma | Lead developer LLBLGen Pro
deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 01-Dec-2006 09:27:35   

Walaa wrote:

What's in the codebehind of the second dropdownlist selectedIndexChanged (when it post back)?

There is no codebehind. This is all of the code.

Walaa wrote:

What's the runtime library version you are using?

I am using the latest version (27-nov-2006).

deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 01-Dec-2006 09:28:41   

Otis wrote:

Please download the latest runtimes, this was fixed some time ago.

I am using the latest version of the runtimes.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 10:51:12   

Reproduced. Strange issue... confused Will look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 11:12:08   

When I check the code, I do nothing wrong... cry I return the SAME data, I don't do a refetch. The datasource has no control over what's going to happen with the data, it simply has to return the data requested. It gets a call to fetch data because of the select parameter. Though it checks if this parameter is different from the previous call. It's not, so it decides not to fetch the data again (so it shouldn't reset any controls) and simply hands over the same data as it had in the previous page request.

Frankly I have absolutely NO idea what to do about this. The frustrating part: there's no documentation. So all I can do is decompile SqlDataSource... AGAIN. rage

Though.. what I can see there is nothing I don't do too... They also create either a new object or return a cached one. I do that too... I'll what happens when the selectparameter isn't there...

(edit): when the select parameter isn't there, I don't get a call to ExecuteSelect of the datasourcecontrol. When the parameter IS there, I do.

Perhaps I mark something as changed which shouldn't... though at the moment I can't find where that might happen as there's no documentation from MIcrosoft what the order is in which everythign is called, so a gazillion breakpoints are necessary to track down what happens at runtime...

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 12:19:24   

When you add: EnableViewState=false to the order combobox, it works.

You then will notice it puts 'SELECTED' attributes in the HTML, otherwise it won't so it will default to the first value.

Why? I have NO idea. Though as I simply can't find a reason why I get a call to ExecuteSelect when there's a parameter based on another control and no call when there's a hardcoded value, and also I can't find any evidence in the sqldatasource control's code that it does something different (it doesn't, my code is based on the .net datasource's code as in: I tried to implement the functionality they apparently also implement, as there's NO documentation why you've to do this).

Frans Bouma | Lead developer LLBLGen Pro
deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 01-Dec-2006 13:34:06   

Frans, are you going to look more into this issue?

I can not use this workaround (disable viewstate), because I use other controls in similar scenarios (e.g. grids) also. Originally I found out this bug while using a grid in a similar scenario. After that I was able to reproduce it with two DropDownLists.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 13:39:14   

deivisg wrote:

Frans, are you going to look more into this issue?

With enableviewstate=false on the dropdownlist control, I can't reproduce the issue anymore. and I can't find anything where to look. My code gets a call from the dropdownlist control to do a select. What's the cause of that, I have NO idea. My code is roughly the same as the sqldatasource in this case.

I can not use this workaround (disable viewstate), because I use other controls in similar scenarios (e.g. grids) also. Originally I found out this bug while using a grid in a similar scenario. After that I was able to reproduce it with two DropDownLists.

Disable viewstate on the control, not the page. When I add a button and a textbox to teh page and select another value in the order dropdown and click the button it's properly remembered.

Also, please re-read what I wrote above. And if you run into a problem with a grid, describe in detail the problem with the grid. This whole asp.net datasource mess is already too frustrating (not because of the problem you reported, but because microsoft designed a very bad non-extensible framework with these datasourcecontrols and didn't document it properly) so please work with me to help you otherwise I'll give up on this issue now.


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default15.aspx.cs" Inherits="Default15" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses" Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="llblgenpro" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <llblgenpro:LLBLGenProDataSource2 ID="CustomerDataSource" runat="server"
            DataContainerType="EntityCollection" EntityFactoryTypeName="NWTest.FactoryClasses.CustomersEntityFactory, NWTest" AdapterTypeName="NWTest.DatabaseSpecific.DataAccessAdapter, NWTestDBSpecific">
        </llblgenpro:LLBLGenProDataSource2>
        <llblgenpro:LLBLGenProDataSource2 ID="OrderDataSource" runat="server"
            DataContainerType="EntityCollection" EntityFactoryTypeName="NWTest.FactoryClasses.OrdersEntityFactory, NWTest" AdapterTypeName="NWTest.DatabaseSpecific.DataAccessAdapter, NWTestDBSpecific">
            <SelectParameters>
                <asp:ControlParameter ControlID="CustomerDropDownList" DefaultValue="" Name="CustomerId" PropertyName="SelectedValue" Type="String" />
            </SelectParameters>
        </llblgenpro:LLBLGenProDataSource2>
        &nbsp;&nbsp;
        <br />
        <asp:DropDownList ID="CustomerDropDownList" runat="server" AutoPostBack="True" DataSourceID="CustomerDataSource"
            DataTextField="CustomerId" DataValueField="CustomerId">
        </asp:DropDownList>
        <asp:DropDownList ID="OrderDropDownList" runat="server" DataSourceID="OrderDataSource"
            DataTextField="OrderId" DataValueField="OrderId" AutoPostBack="True" EnableViewState="false">
        </asp:DropDownList>
        &nbsp;&nbsp;<br />
        <asp:button ID="btnTest" runat="server" Text="Postback" OnClick="btnTest_Click"/>
        <asp:TextBox ID="txtTest" runat="server"/>
    </div>
    </form>
</body>
</html>

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Default15 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void btnTest_Click(object sender, EventArgs e)
    {
        txtTest.Text = "Postback!";
    }
}
Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 14:11:47   

Addition: WHen the EnableViewState is false on the dropdownlist, there is a call to ExecuteSelect on the datasource though it's done when the page is setup. So as there's no new data to load, the same data is returned, which is then showing up nicely in the dropdownlist and the proper selected value is indeed marked SELECTED.

When the EnableViewState is set to true on the dropdownlist, there is a call to the executeselect on the datasource though this is done with a different stacktrace: the call originates from a different origin and I assume (nothing is certain here, no docs!) the calling code treats the data returned differently.

Again, I have NO idea why it does work with the sqldatasource and not with my code as all the code that's relevant works the same and the sqldatasource simply also returns an object from ExecuteSelect when it's called, so it's somewhere else but I have no idea where in the 2000 lines I have to look... (and trust me, that happens almost never, only with the datasourcecontrols I have no clue what to do and where to look as the whole framework they operate in is obscure and fragile... )

callstack WITH viewstate:


>   SD.LLBLGen.Pro.ORMSupportClasses.DLL!SD.LLBLGen.Pro.ORMSupportClasses.LLBLGenProDataSourceView2.ExecuteSelect( System.Web.UI.DataSourceSelectArguments arguments = {System.Web.UI.DataSourceSelectArguments}) Line 1054 C#
    System.Web.dll!System.Web.UI.WebControls.ListControl.OnDataBinding(System.EventArgs e) + 0x5d bytes 
    System.Web.dll!System.Web.UI.WebControls.ListControl.PerformSelect() + 0x20 bytes   
    System.Web.dll!System.Web.UI.WebControls.BaseDataBoundControl.DataBind() + 0x47 bytes   
    System.Web.dll!System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() + 0x53 bytes    
    System.Web.dll!System.Web.UI.WebControls.ListControl.OnPreRender(System.EventArgs e = {System.EventArgs}) + 0x1b bytes  
    System.Web.dll!System.Web.UI.Control.PreRenderRecursiveInternal() + 0x4e bytes  
    System.Web.dll!System.Web.UI.Control.PreRenderRecursiveInternal() + 0xa2 bytes  
    System.Web.dll!System.Web.UI.Control.PreRenderRecursiveInternal() + 0xa2 bytes  
    System.Web.dll!System.Web.UI.Page.ProcessRequestMain(bool includeStagesBeforeAsyncPoint = true, bool includeStagesAfterAsyncPoint = true) + 0x551 bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint = true) + 0x4d bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequest() + 0x57 bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext context) + 0x13 bytes   
    System.Web.dll!System.Web.UI.Page.ProcessRequest(System.Web.HttpContext context) + 0x32 bytes   
    App_Web_azinjwr2.dll!ASP.default15_aspx.ProcessRequest(System.Web.HttpContext context = {System.Web.HttpContext}) + 0x2f bytes  C#
    System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep. Execute() + 0x9b bytes    
    System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool completedSynchronously = true) + 0x41 bytes  

callstack with viewstate is false:


>   SD.LLBLGen.Pro.ORMSupportClasses.DLL!SD.LLBLGen.Pro.ORMSupportClasses.LLBLGenProDataSourceView2.ExecuteSelect( System.Web.UI.DataSourceSelectArguments arguments = {System.Web.UI.DataSourceSelectArguments}) Line 1054 C#
    System.Web.dll!System.Web.UI.WebControls.ListControl.OnDataBinding(System.EventArgs e) + 0x5d bytes 
    System.Web.dll!System.Web.UI.WebControls.ListControl.PerformSelect() + 0x20 bytes   
    System.Web.dll!System.Web.UI.WebControls.BaseDataBoundControl.DataBind() + 0x47 bytes   
    System.Web.dll!System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() + 0x53 bytes    
    System.Web.dll!System.Web.UI.WebControls.DropDownList.LoadPostData(string postDataKey = "OrderDropDownList", System.Collections.Specialized.NameValueCollection postCollection) + 0x1e bytes    
    System.Web.dll!System.Web.UI.WebControls.DropDownList.System.Web.UI.IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) + 0xc bytes    
    System.Web.dll!System.Web.UI.Page.ProcessPostData(System.Collections.Specialized.NameValueCollection postData, bool fBeforeLoad = true) + 0x199 bytes   
    System.Web.dll!System.Web.UI.Page.ProcessRequestMain(bool includeStagesBeforeAsyncPoint = true, bool includeStagesAfterAsyncPoint = true) + 0xec1 bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint = true) + 0x4d bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequest() + 0x57 bytes 
    System.Web.dll!System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext context) + 0x13 bytes   
    System.Web.dll!System.Web.UI.Page.ProcessRequest(System.Web.HttpContext context) + 0x32 bytes   
    App_Web_hwa0yqx8.dll!ASP.default15_aspx.ProcessRequest(System.Web.HttpContext context = {System.Web.HttpContext}) + 0x2f bytes  C#
    System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep .Execute() + 0x9b bytes    
    System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool completedSynchronously = true) + 0x41 bytes  
    System.Web.dll!System.Web.HttpApplication.ResumeSteps(System.Exception error) + 0x163 bytes 


One interesting thing is that when viewstate is enabled on the combobox: I get an event that the parameters have changed AFTER the page loaded. (relevant code is identical to sqldatasource control's code) This event raises the changed event of the datasourcecontrol and AFTER that the select call takes place

However... when I have viewstate disabled on the combo box, this event NEVER happens.... Why? I have no idea, though the same steps occur: page load event occurs, parameters are updated but that doesn't raise an event to signal the parameters have been changed. The select call still comes but from a different routine. As the datasourcecontrol by itself sees the select parameters haven't changed, it doesn't do a fetch call again and simply returns the same data.

Now if anyone knows any documentation why this happens, I'm all ears. But at the moment I have 100% no idea.

(edit) what's also silly is that the parametercollection object raises the changed event while the only parameter in it isn't changed at all... confused

(edit) Ok, the parameter contents gets changed, because the customer combobox value is inserted as the value of the parameter.

I find it strange that the parameter doesn't have a value defined at all, as I do have tracking enabled and it's thus stored (has to be) in the viewstate... So the value set after the page is loaded is then changing it.

It's even more strange that this happens when enableviewstate is enabled while it does work properly when enableviewstate is disabled...

(edit) ok, when the selectparameter is a defaultvalue parameter, the parameter already has the value to set (gets the same value) and therefore doesn't change and nothing happens.

It seems that the original parameter values aren't stored in the viewstate apparently even though everything has viewstate enabled. So the read from the viewstate isn't setting any parameter value, then the value is set from the customer combobox, obviously a change and then the select call is made.

Looking further.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 15:13:18   

OK, the parameter values aren't saved properly in the viewstate. So the parameter values are changed (from null to the value selected) every postback. My datasourcecontrol contains code which tracks this, and doesn't do a new fetch if the old value is equal to the current value, however I now have the feeling this appears to be the wrong code for the same issue.

I'll try something out and see if that fixes this issue.

Frans Bouma | Lead developer LLBLGen Pro
deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 01-Dec-2006 15:17:45   

Glad you found something. Let me know if you still need some info. I could describe you the problem with grid but I am using Telerik's RadGrid. Not sure if you have access to it.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 01-Dec-2006 15:32:09   

Tears of joy!smile

Ok, a couple of months back I fixed an issue (hence the reason I said earlier to download the latest version as this was fixed some time ago) where a combobox was reset to the initial value (when bound to a datasource control AND with a select parameter) due to a postback from a button. I then discovered after an afternoon of searching that the selectparameters apparently were different so I had to cache the old ones and compare with the current ones, and if there was no difference simply return the old cached data. This solved that particular problem, but it was in fact the SAME issue.

I know simply cache the selectparameter values properly like the datasource controls of ms do (thanks to the one true documentation we have: reflector wink ) and it works like a charm! simple_smile

Fixed in build 2.0.0.061201 of the runtime libraries. If you need the runtimelibs NOW please let me know otherwise wait a couple of days before we upload a new build to the website.

(I'll now clean up that old fix as it's not needed anymore, so it's not fully finalized yet).

Ok done.

Frans Bouma | Lead developer LLBLGen Pro
deivisg
User
Posts: 12
Joined: 14-Nov-2006
# Posted on: 01-Dec-2006 15:36:55   

Congratulations! simple_smile