StrataFrame Forum

Issue with BOs inheriting from the same base BO

http://forum.strataframe.net/Topic19668.aspx

By Andria Jensen - 9/24/2008

I am using several BOs which inherit from the same base BO to bind to several different reports.  So for example:

BO1, BO2, and BO3 all inherit from BO.

BO1 is used on Report1, BO2 is used on Report2, and BO3 is used on Report3. 

In all of these cases, the inherited BO is just extended a few more custom properties and fill methods to be used specifically for each of the reports.   I can open the application and run one of these reports without error.  However, if I then try to run another of the three reports I get an error: "Object does not match target type".  So, if I run the app, I can run Report1 successfully but then if I try to run either Report2 or Report3 it will throw the error.  I can still run Report1 as many times as I want.  The same is true no matter what the order.  If I were to run Report2 first, it would run successfully but Report1 and Report3 would give the error. 

This is only happening on reports which are bound to BOs that inherit from the same base BO.  The reports can be run successfully as long as no other report bound to a BO that shares the base BO has been run.  It seems as if something is being shared between the BOs for some reason because they are inheriting from the same base. 

Here is the call stack I get...I have highlighted where I think the relevancy begins for you:

at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at MicroFour.StrataFrame.Business.ReflectionPropertyDescriptor.GetValue(Object component)
at DevExpress.Data.Helpers.BaseListDataControllerHelper.GetRowValue(Int32 listSourceRow, Int32 column)
at DevExpress.Data.Storage.DataStorageObjectComparer.CreateStorage(VisibleListSourceRowCollection rows, BaseDataControllerHelper dataHelper, Int32 column)
at DevExpress.Data.Helpers.DataColumnSortInfoCollection.CreateColumnStorages(VisibleListSourceRowCollection visibleListSourceRows, BaseDataControllerHelper helper)
at DevExpress.Data.DataController.DoSortRows()
at DevExpress.Data.DataController.DoRefreshCore(Boolean useRowsKeeper)
at DevExpress.Data.DataController.DoRefresh(Boolean useRowsKeeper)
at DevExpress.Data.DataControllerBase.DoRefresh()
at DevExpress.Data.DataController.OnSortInfoCollectionChanged(Object sender, CollectionChangeEventArgs e)
at DevExpress.Data.NotificationCollectionBase.OnCollectionChanged(CollectionChangeEventArgs e)
at DevExpress.Data.NotificationCollectionBase.EndUpdate()
at DevExpress.Data.Helpers.DataColumnSortInfoCollection.ClearAndAddRange(DataColumnSortInfo[] sortInfos, Int32 groupCount)
at DevExpress.XtraReports.Native.SortedListController.GroupData(DataColumnSortInfo[] sortInfos)
at DevExpress.XtraReports.Native.SortedListController.GroupData(GroupField[] groupFields)
at DevExpress.XtraReports.Native.SortedListController.GroupData(SortedListController listController, XRGroupCollection groupCollection, GroupFieldCollection groupFields)
at DevExpress.XtraReports.UI.XtraReportBase.get_DataBrowser()
at DevExpress.XtraReports.UI.XtraReportBase.BuildDocument(DocumentBuilder builder)
at DevExpress.XtraReports.UI.XtraReport.CreateDocument(PrintingSystem ps, Single progressRange)
at DevExpress.XtraReports.UI.XtraReport.CreateDocument(Single progressRange)
at DevExpress.XtraReports.UI.XtraReport.CreateDocument()
at BBS.Reports.BaseReport.Process(ParmTable ParmTable, ProgressBarControl& ProgressBar) in C:\Cadence 1.1\BBS.Reports\BaseReport.vb:line 215

By Trent L. Taylor - 9/24/2008

You should be using the Custom BBS class that was implemented in 1.6.6 as this template will inherantly fix your problem.  Here is the issue, the custom properties have already been evaluated for one type.  The template in which I am referring will create a report BO with the AreCustomBindingSourcesEvaluated property which will ensure that each of the unique types will re-evaluate the custom properties.  If you just create a new Custom BBS through the Add New Item within a solution and create a reporting BO, you will see the code I am talking about (the property I named above may be slightly different...I am shooting from the hip there).  But that is your problem and why we created this interface and logic...specifically to prevent this error and also to make creating reporting objects far easier.
By Andria Jensen - 9/24/2008

Great!  Thanks for the help....glad there is a fix. 

I do have a question though...is there a workaround at all if I don't upgrade to 1.6.6?  We are on the verge of doing a release in the next couple of weeks and are always leary of doing an upgrade of our 3rd party controls late in a release cycle.  We had planned to do the 1.6.6 upgrade at the beginning of the next release cycle so it could be adequately tested with the rest of the software.  Any ideas?

By Trent L. Taylor - 9/25/2008

Yes, the logic is the same. Just place this code in all of the inherited BOs :

#Region " Private Fields "

        Private Shared _AreCustomDescriptorsEvaluated As Boolean = False

#End Region

#Region " Protected Methods "

        ''' <summary>
        ''' Determine if the custom descriptors are going to be evaluated
        ''' </summary>
        ''' <remarks></remarks>
        Protected Overrides ReadOnly Property AreCustomDescriptorsEvaluated() As Boolean
            Get
                '-- Establish Locals
                Dim r As Boolean = _AreCustomDescriptorsEvaluated

                '-- Do not eval the desciptors again
                _AreCustomDescriptorsEvaluated = True

                '-- Return results
                Return r
            End Get
        End Property

#End Region

This will override the descriptors evaluation property and then each inherited BO will ensure to re-evaluate itself preventing the error.  The new Custom BBS was created and designed specifically for this purpose (creating reporting objects and/or a single object based model), so you will definitely want to look at this when you load 1.6.6.

By Andria Jensen - 9/25/2008

I actually already have this logic in all of my inherited BOs.  Is it possible that there is something else I need to do?
By Trent L. Taylor - 9/25/2008

If you have the same field that gets used in the child and then you have a strong-typed property on the inherited class you could have this happen.  For example, if I use a MyBo.CurrentRow,Item("MyField") and then on the inherited BO I have a strong-typed property for "MyField" it would cause this.  In this case you would want to move the strong-typed property up the food-chain to the main BO.  This would happen even if you are pulling these fields from a BBS (grid) or a ListView on the parent BO.  So check this....but the good news it should be one or the other.
By Andria Jensen - 9/25/2008

I'm really not sure I understand what you said.  Are you saying that if I create a property MyField in my inherited BO which is returning Me.CurrentRow.Item("MyField") that it could be causing the problem?  I am doing this, but I guess I don't know if that's what you are saying is causing the problem.  If so, wouldn't moving those properties up to the Base BO defeat the purpose of inheriting anyway?
By Trent L. Taylor - 9/25/2008

No, that is not really what I am saying.

BO1.CurrentRow.Item("MyField")
BO2.MyField

In the above example let's assume that BO2 inherits BO1.  If I reference a field in the BO1 like shown and then the inherited BO referneces the same field name through a strong-typed property, it would produce the reflection issue.  The same problem would occur if the roles were reversed as well.  So in this case, if the strong-typed property were moved from the BO2 to BO1 it would resolve the error because BO2 inherits from BO1 and each BO will re-evaluate the MyField property, thus eliminating the reflection contention.

By Andria Jensen - 9/30/2008

I went ahead and did the upgrade, but have not been able to correct the issue.  I created a Custom Binding Source for each of the BOs that were inheriting from the same base and being used as a report data source.  I then changed the report to use those binding sources as the data sources.  I am still getting the same error.  Any ideas?   I am going to try to reproduce this in a small project as well...
By Andria Jensen - 9/30/2008

I have resolved this issue, but wanted to post my explanation for future reference.  Either this is a different issue than what you explained or I didnt fully understand what you were telling me the issue was.  I think I most likely didnt understand it correctly.  Either way, I'm not sure why the upgrade did not resolve it.

Basically I have BaseBO with ChildBO1 and ChildBO2 both inheriting from BaseBO.  ChildBO1 and ChildBO2 both have custom properties named the same thing, and accessing the same field in the data table.  This is creating the issue.  So if I have a custom property in BOTH child BOs like this :

Public ReadOnly Property MyFieldName() as String
  Get
    Return Me.CurrentRow("MyFieldName")
  End Get
End Property

It should really be moved up to the BaseBO as a property there.  I changed it to prevent error if the query doesnt return this custom field:

Public ReadOnly Property MyFieldName() as String
  Get
    If Me.CurrentDataTable.Columns.Contains("MyFieldName") Then
      Return Me.CurrentRow("MyFieldName")
    Else 
      Return ""
    End If
  End Get
End Property

So moving the custom property declaration the child BOs had in common to the base level corrected the issue and allowed me to access it at the child level without error.  However, when I did the upgrade and changed my reports to use custom BBS objects I created, the issue remained.  I thought this was addressed in 1.6.6? 

By Trent L. Taylor - 10/1/2008

That was exactly what I was trying to relay but I apparently did not get the point across.  In all of the examples that I gave you I used BO2 and BO2, but the same thing comes into play if the BaseBO ever references this field outside of a strong-typed property and then through a strong-typed property on any downstream call.  So you ultimately got the problem fixed, but it was just in a different object that my examples were stating.

As for this being resolved in 1.6.6, I was referrring to the template having this logic within it.  But the exact same problem would occur if you setup the same scenario.  We could re-evaluate every custom property, on every BO, on every reference...but this would drastically impact performance (in a negative way) as the custom properties only need to be evaluated once.  The problem comes (and this is standard .NET) when inheritance comes into play.  Because through reflection, we have an inherited BO that has a custom property (i.e. MyField) which gets evaluated properly.  But if the BO in which it is inherited ever references this field even through a CurrentRow reference, the BO will have an issue the moment the second BO is brought up as it will try to evaluate that custom property incorrectly (or rather .NET will through reflection).  So by placing the custom property on the lowest common denominator BO that will ever access that property, it will resolve the problem.

By Andria Jensen - 11/5/2009

I have run into this error message again, and this time cannot find the root of it.  I have spent countless hours trying to track it down, and now need a little bit of guidance if possible.

I have gotten this before, and it has always been a case of two inherited BOs having the same cutom property and having to move that custom property up to the base BO.  Or it has been a case of wrongly accessing the base BO property or inherited BO property at a level it shouldn't be.  Well, I can't see that's the case with my current situation.

I have it narrowed down to the following recreation:
- There are two BOs, BO2 which inherits from the base BO1.
- I have form1 which only houses a BO2 instance.
- I have from2 which only houses a grid that connects to a BBS which uses BO1 as its source.
- If I open form1, then open form2, the from loads and the grid populates but as soon as I go off that form or do anything else, I get the "object does not match target type" error.

Now, I have searched for any commonly named properties. I have actually commented out every custom property at the base level (BO1) and still get the problem. I only have two custom properties on BO2, which are only accessed through BO2. 

So my question is basically this:  is there any other circumstance in which this error may occur that hasn't already been covered in this ticket?  I've lost a few days on this error and now just have no idea of where to go with it.  Please offer any help you can, it will be much appreciated.  Thanks!!