BusinessBase as chilld property (One to one OR mapping)

BusinessBase as chilld property (One to one OR mapping)

Old forum URL: forums.lhotka.net/forums/t/5307.aspx


Joffies posted on Wednesday, August 27, 2008

I am not sure if i am going about this in the right way....

I have two tables, Award and AwardVestingSettings and the relationship between these are 1 to 1.

I have a businessbase class

Public Class Award
     
Inherits BusinessBase(Of Award)
.....

Within this class I have  property that represents the awardvesting setting table

.....

Private Shared VestingSettingProperty As PropertyInfo(Of AwardVestingSetting) = RegisterProperty(Of AwardVestingSetting)(GetType(Award), New PropertyInfo(Of AwardVestingSetting)("VestingSetting", "VestingSetting"))

''' <Summary>
''' Gets and sets the VestingSetting value.
''' </Summary>

Public Property VestingSetting() As AwardVestingSetting
Get
   
Return GetProperty(Of AwardVestingSetting)(VestingSettingProperty)
End Get

Set(ByVal value As AwardVestingSetting)
    SetProperty(
Of AwardVestingSetting)(VestingSettingsProperty, value)
End Set
End Property

......

AwardVestingSetting is also a businessbase class

......

Public Class AwardVestingSetting
    
Inherits BusinessBase(Of AwardVestingSetting)

.....

I am trying to make use of this through winforms databinding but cannnot set databinding through the designer for the properties of the AwardVestingSetting child object. I am not sure if I am implementing the one to one relationship as property correctly...?

Thanks

 

ajj3085 replied on Wednesday, August 27, 2008

Well, first off make sure you're designing your objects based on the use case, not on the database schema.  But yes, you can have a single BusinessBase subclass that is a child of another BusinessBase.  I don't think however you'd want a public property setter for the child BO though. 

What you'll need to do for databinding is create a second BindingSource component.  It's data source will be the primary BindingSource component for the Award class.  The AwardVestingSetting's BindingSource's DataMember property would be set to "VestingSetting". 

If you want to make things similpler, you can make AwardVestingSetting an internal class, and expose it's properties via the Award class.  This would be a facade pattern.  But I would only do that if AwardVestingSetting has a lot of it's own rules, or if AwardVestingSetting is an abstract class and you're going to subclass it because you have diffferent VestingSettings with their own unique behaviors.

Joffies replied on Wednesday, August 27, 2008

Thanks for the reply ajj3085. I agree with the approach of basing objects on the use case first. 

I cannot seem to pickup the property VestingSetting as a Datamember for some reason? The property is Public so it should be visible as far as i can see..

 

 

ajj3085 replied on Wednesday, August 27, 2008

Ya, I can't remember if it will show up in the dropdown, but you should be able to type VestingSetting manually into the designer anyway.

pfeds replied on Wednesday, August 27, 2008

As said, you probably need to think about the behaviour of your objects and not your database schema.  Would you class Award and AwardVestingSettings as different objects, or one object that just happens to reside in more than one database table?

If they're two seperate objects then it could be worth using two datasources instead of one, with the second datasource calling AwardVestingSettings.GetAwardVestingSettings(award.VestingSettingsId);

If they do need to be a single object then it could be worth storing the AwardVestingSettings object internally to the Award class. You can then expose the AwardVestingSettings properties on the Award class.

Here's another example that may help:

A Customer may have a primary Address (mandatory) as well as a collection of other addresses (shipping, billing, alternate addresses etc).  The primary address will be a 1-1 to the customer, and an application may treat the primary address as such.  This will allow you to do the following:

Customer newCustomer = Customer.NewCustomer();

newCustomer.Name = "Bob Monkhouse";

newCustomer.StreetAddress = "41 Country Lane";

Internally the street address is being stored in an Address object, but the user of the object does not need to see that.  It also makes databinding clearer.

The Customer class would contain the following:

public string StreetAddress

{

   get

   {

      return this.primaryAddress.StreetAddress

   }

}

I hope this helps.

Joffies replied on Wednesday, August 27, 2008

Thanks for the reply and the insight to the use case/problem.

The Award and AwardVestingSetting should exist within in the same object in my use case and as far as I understand that is why the VestingSettings property is therefore allowing the usecase be exposed as single object and all the CRUD methods being handled by the parent object.

The AwardVestingSetting class was created from the point of view that it will be a child property so all the factory and data access methods were declared to identify it as being a child object and only exist within the parent context.

Factory Methods
-----

Public Shared Function NewAwardVestingSetting(ByVal AwardId As Integer) As AwardVestingSetting

If Not CanAddObject() Then
    Throw New System.Security.SecurityException(" User not authorised to add a Award")
End If

Return DataPortal.CreateChild(Of AwardVestingSetting)(New SingleCriteria(Of AwardVestingSetting, Integer)(AwardId))

End Function

Public Shared Function GetAwardVestingSetting(ByVal awardId As Integer) As AwardVestingSetting

If Not CanGetObject() Then
     Throw New System.Security.SecurityException("User not authorised to to view a Award")
End If

Return DataPortal.FetchChild(Of AwardVestingSetting)(New SingleCriteria(Of AwardVestingSetting, Integer)(awardId))

End Function

----
Data Access Methods

Private
Sub Child_Fetch(ByVal criteria As SingleCriteria(Of AwardVestingSetting, Integer))
        ...............
End Sub

Private Sub Child_Insert()
        ................
End Sub

Private Sub Child_Update()
       .................
End Sub

Joffies replied on Wednesday, August 27, 2008

OK, somethings fishy going on when using specifying a property of BusinessBase type and using Undo.

My Parent class has two properties of which both are BusinessListBase and undo works fine for these two.

If I  attempt to load the of the BusinessBase type (AwardVestingSetting) property and then attempt undo I get the lovely  Edit level mismatch in copystate error. :).

Private Sub RebindUI(ByVal saveObject As Boolean, ByVal rebind As Boolean)

' disable events

Me.AwardBindingSource.RaiseListChangedEvents = False

Me.TransactionsBindingSource.RaiseListChangedEvents = False

Me.VestingsBindingSource.RaiseListChangedEvents = False

Me.VestingSettingsBindingSource.RaiseListChangedEvents = False

Try

' unbind the UI

UnbindBindingSource(Me.VestingSettingsBindingSource, saveObject, False)

UnbindBindingSource(Me.VestingsBindingSource, saveObject, False)

UnbindBindingSource(Me.TransactionsBindingSource, saveObject, False)

UnbindBindingSource(Me.AwardBindingSource, saveObject, True)

' save or cancel changes

If saveObject Then

_award.ApplyEdit()

Try

_award = _award.Save

Catch ex As Csla.DataPortalException

MessageBox.Show(ex.BusinessException.ToString(), _

"Error saving", MessageBoxButtons.OK, _

MessageBoxIcon.Exclamation)

Catch ex As Exception

MessageBox.Show(ex.ToString(), _

"Error Saving", MessageBoxButtons.OK, _

MessageBoxIcon.Exclamation)

End Try

Else

_award.CancelEdit()

End If

Finally

' rebind UI if requested

If rebind Then

BindUI()

End If

' restore events

Me.AwardBindingSource.RaiseListChangedEvents = True

Me.TransactionsBindingSource.RaiseListChangedEvents = True

Me.VestingsBindingSource.RaiseListChangedEvents = True

Me.VestingSettingsBindingSource.RaiseListChangedEvents = True

If rebind Then

' refresh the UI if rebinding

Me.AwardBindingSource.ResetBindings(False)

Me.TransactionsBindingSource.ResetBindings(False)

Me.VestingsBindingSource.ResetBindings(False)

Me.VestingSettingsBindingSource.ResetBindings(False)

End If

End Try

End Sub

In essence all three properties are the same except for the VestingSettings being of BusinessBase Type.

Copyright (c) Marimer LLC