CodeSmith Community
Your Code. Your Way. Faster!

DataParameter and EntityDataSource

Latest post 07-30-2008 5:03 PM by rwil02. 6 replies.
  • 11-14-2006 12:12 AM

    • Evan
    • Top 150 Contributor
    • Joined on 09-19-2006
    • Seattle, WA
    • Posts 30
    • Points 820

    DataParameter and EntityDataSource

    Hi Guys,

    I encountered a situation today in which I needed an entitydatasource (let's say SalaryDataSource) to select data based on an FK value in another entitydatasource (let's say EmployeeDataSource) on the page. Specifically, the SalaryDataSource has SelectMethod="GetByEmpID". I want the EmpID value to come from the selected entity in the employeedatasource on the page. It seemed like the DataParameter might usable to extract the EmpID from the EmployeeDataSource. Here's how I configured the DataParameter to provide the EmpID param to the SalaryDataSource:

                       <data:SalaryDataSource ...>
                        <Parameters>
                        <data:DataParameter DataSourceID="EmployeeDataSource" Name="EmpID" PropertyName="EmpID" Type="Int32" EntityKeyName="EmpID"/>
                        </Parameters>
                       </data:SalarydataSource>

     What happens inside the DataParameter class is confusing me. In the Evaluate() method, the property value is retrieved correctly from the datasource identified in datasourceid. That's good. Then, that value is mashed up into an SQL-like syntax:

                        value = String.Format("{0} IN ({1})", propertyName, values.ToString()

     The result here is a Parameter whose value is something like: "EmpID IN (1413)"  The way I see it is the param value should just be '1413' (the example EmpID in this case). Am I completely mis-using the DataParameter? Is there something else that can retrieve a property's value from a datasource? I hacked the DataSource class to give me what I want:

      Line 94: values.Add(temp.ToString()); // values.Add(String.Format("'{0}'", temp));

    Line 100: value = values.ToString(); // value = String.Format("{0} IN ({1})", propertyName, values.ToString()); 

    Any input/advice?

    Cheers,

    Evan
     

     

     

     

    Filed under:
    • Post Points: 35
  • 08-03-2007 10:51 AM In reply to

    • MikeBosch
    • Top 500 Contributor
    • Joined on 06-04-2007
    • Miami, FL
    • Posts 16
    • Points 495

    Re: DataParameter and EntityDataSource

    I'm still having an issue getting this to work.  Any ideas?

    • Post Points: 35
  • 09-03-2007 10:08 PM In reply to

    • goody
    • Not Ranked
    • Joined on 09-03-2007
    • Posts 5
    • Points 140

    Re: DataParameter and EntityDataSource

    Hi Guys, I've just come across this problem and another in the Evaluate function of the DataParameter. The DataSource that we have specified by DataSourceId is located in our master page, similar to bdiaz example http://community.codesmithtools.com/forums/p/3114/12874.aspx#12874

    So we changed the following line 75 to ensure it searches from the top level:

    //_dataSource = control.FindControl(DataSourceID) as IListDataSource;
    _dataSource = control.Page.Form.FindControl(DataSourceID) as IListDataSource;

     
    We also had to change the following line ~90:

    //temp = EntityUtil.GetPropertyValue(item, EntityKeyName);
    temp = EntityUtil.GetPropertyValue(item, propertyName);

    I'm not sure about this change and could use some advice? maybe we just need to put the property name in the EntityKeyName attribute?

    Then we had to make the changes mentioned above by Evan which make sense to me but i guess wouldn't work if there were more that one value in 'values'. Maybe an additional change would need to be made in the EntityKey class Load function to interpret the values given by the DataParameter....but really just a stab in the dark. Any feedback on this would be great!

     

    Filed under:
    • Post Points: 35
  • 09-17-2007 6:51 PM In reply to

    • bgjohnso
    • Top 10 Contributor
    • Joined on 09-15-2005
    • Spokane, WA
    • Posts 767
    • Points 22,605

    Re: DataParameter and EntityDataSource

    Goody,

    I think your changes look good.  I would probably leave both FindControl statements in there so it searches the current container first and then moves up to page level if it can't find the datasource:

    _dataSource = control.FindControl(DataSourceID) as IListDataSource;
    if (_dataSource == null) _dataSource = control.Page.Form.FindControl(DataSourceID) as IListDataSource;

    The second change also looks correct.  By using propertyName instead of you can get a non-key value by specifying the PropertyName property.  By using EntityKeyName, you can only ever return the key, which may not be what you want.

    As for Evan's changes, I think they make sense as well.  I can't think of anywhere where the IN clause would make sense.

    I'll try and get these changes checked in shortly.

    Ben Johnson
    ------------------------------
     Member of the .NetTiers team
     Visit http://www.nettiers.com
    ------------------------------

    • Post Points: 35
  • 11-28-2007 3:56 PM In reply to

    • Jerph
    • Not Ranked
    • Joined on 09-21-2007
    • Posts 8
    • Points 190

    Re: DataParameter and EntityDataSource

    First I'd like to thank mike and Goody.  I've gotten DataParameter to work for me using essentially what's on this post, and it's solved my problem.  I think this is an important update to NetTiers. 

    I have a few points however:

    1. I think the intent of DataParameter was to build a where clause for GetPaged.  I don't see any reason why it wouldn't work for this purpose, except...
    2. ... _dataSource = control.FindControl would never work, since control in the context of Evaluate is the DataSource that contains this DataParameter.  There's no way that one DataSource can contain another DataSource, right?

    From #1, I think the changes suggested in this post would be changing the intent of the control.  I think you should be able to specify the type of return: either a WhereClause expression like it does currently, or a single value as suggested above.  I'd suggest a new bool property (I don't know, UseWhereClauseFormat?) that would toggle this.

    From point #2, it seems like this parameter has never worked.  Should changes we make to DataParameter be considered a "Breaking Change" in that case?

    For finding the DataSource control, I suggest that even Page.Form.FindControl(DataSourceID) is a bad move: What if the target data source is in a user control?  control.NamingContainer.FindControl would be better.  Unfortunately, that doesn't work if the parameter's DataSource is inside a FormView and the target DataSource is outside of it (that's a problem I ran into).  The solution that eventually worked for me was to add this function to FormUtilBase:

     ------
            /// <summary>
            /// Searches for the specified control id in the nearest INamingContainer
            /// (searching outward from the specified control).
            /// </summary>
            /// <param name="control">The <see cref="Control"/> at which to begin the search.</param>
            /// <param name="controlId">The id parameter value.</param>
            /// <returns></returns>
            public static Control FindNearestControl(Control control, String controlId)
            {
                Control found = null;

                if ( control != null )
                {
                    if (control is INamingContainer)
                    {
                        found = control.FindControl(controlId);
                    }

                    if (found == null)
                    {
                        found = FindNearestControl(control.NamingContainer, controlId);
                    }
                }

                return found;
            }

    ------

    And my evaluate function looks like this:

    ------

            protected override Object Evaluate(HttpContext context, Control control)
            {
                String value = String.Empty;

                if ( _dataSource == null && control != null )
                {
                    _dataSource = FormUtil.FindNearestControl(control, DataSourceID) as IListDataSource;
                }

                if ( _dataSource != null )
                {
                    IEnumerable entityList = _dataSource.GetEntityList();

                    if ( entityList != null )
                    {
                        IList list = EntityUtil.GetEntityList(entityList);
                        Object temp;

                        foreach ( Object item in list )
                        {
                            temp = EntityUtil.GetPropertyValue(item, PropertyName);

                            if ( temp != null )
                            {
                                value = temp.ToString();
                                break;
                            }
                        }
                    }
                }

                return value;
            }
    ------

    This of course only returns the single value.  It should be simple to add the old behavior depending on a new bool property.  Anyone have thoughts on this approach?  If you guys like it, i'd be happy to offer it as a patch.

    Thanks!

    Filed under:
    • Post Points: 35
  • 07-30-2008 4:50 AM In reply to

    • rwil02
    • Not Ranked
    • Joined on 07-30-2008
    • Posts 2
    • Points 10

    Re: DataParameter and EntityDataSource

    Here's what I consider to be a better alternative.

    DataBoundParameter, which binds against properties of the current databinding object.

    ===============================================================

     

         public class DataBoundParameter : Parameter
        {
            private Control _bindingControl;
            private String _propertyName;
            private String _format = "";

            /// <summary>
            /// Initializes a new instance of the DataBoundParameter class.
            /// </summary>
            public DataBoundParameter()
            {
            }

            /// <summary>
            /// Gets or sets the PropertyName.
            /// </summary>
            public String PropertyName
            {
                get { return _propertyName; }
                set { _propertyName = value; }
            }
            /// <summary>
            /// Gets or sets the Format.
            /// </summary>
            [System.ComponentModel.DefaultValue("")]
            public String Format
            {
                get { return _format; }
                set { _format = "" + value; }
            }

            private Control GetBindingContainer(Control ctl)
            {
                while (ctl != null)
                {
                    if (ctl is INamingContainer)
                    {
                        if (ctl is UserControl)
                        {
                            return ctl;
                        }
                        if (ctl is FormView)
                        {
                            return ctl;
                        }
                        if (null == ctl.GetType().GetInterface("System.Web.UI.INonBindingContainer"))
                        {
                            return ctl;
                        }
                    }
                    ctl = ctl.Parent;
                }
                return null;
            }
     


            /// <summary>
            /// Updates and returns the value of the DataBoundParameter object.
            /// </summary>
            /// <param name="context">The current System.Web.HttpContext of the request.</param>
            /// <param name="control">The System.Web.UI.Control that the parameter is bound to.</param>
            /// <returns>A System.Object that represents the updated and current value of the parameter.</returns>
            protected override Object Evaluate(HttpContext context, Control control)
            {
                if (_bindingControl == null)
                {
                    _bindingControl = GetBindingContainer(control);
                }
                if (_bindingControl != null)
                {
                    return DataBinder.GetPropertyValue(DataBinder.GetDataItem(_bindingControl), PropertyName, Format);
                }
                return string.Empty;
            }
        }

     

    [Mucked up editor related paste garbage deleted]

    • Post Points: 5
  • 07-30-2008 5:03 PM In reply to

    • rwil02
    • Not Ranked
    • Joined on 07-30-2008
    • Posts 2
    • Points 10

    Re: DataParameter and EntityDataSource

    Should include sample usage I guess :)

     <data:DrugDataSource ID="DrugIDDrugDataSource" runat="server" SelectMethod="Get">
       <Parameters>
           <data:DataBoundParameter Name="DrugID" PropertyName="DrugID" />
       </Parameters>
    </data:DrugDataSource>

    • Post Points: 5
Page 1 of 1 (7 items) | RSS
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems