Oct
06
2010

XPO Associations + Constants = Safety

User Rating: / 0
PoorBest 

More on my topic of ensuring all references in your class are strongly typed.

NOTE: Please see comments below, in most cases (if not all) you don't have to specify the optional association arguments, will verify when you need to use these parameters and place that on the Wiki. For those who do specify the name the post still provides some ideas but ultimately doesn't really apply to every day use. my thx to Noxe for bringing this to my attention.

How many times have you received a “PropertyTypeMismatchException” because you didn’t name your association the same between two classes?

It is easy to put a type in and cause some frustration while trying to find which side.

How can you handle this easier? Easy just declare Constant on one side of your association and reference that for your AssociationAttribute.

I am defining my Association Constant on the one side of the relationship, technically another option could be to create a Module/Static class called “Associations” and place your constants in there, but personally I prefer them to be apart of the objects the association is based on.

Here is an example of a “Strongly Typed” XPO class with Association, the only place strings are used is in the Constant declaration and within the FieldsClass itself. This makes it almost kiddy safe as you will receive compile errors if you start refactoring and not changing the bits you should.

Hope it helps

Public Class Company
    Inherits XPObject

    Private fTradingName As String
    Public Property TradingName As String
        Get
            Return fTradingName
        End Get
        Set(ByVal Value As String)
            SetPropertyValue(Fields.TradingName.PropertyName, fTradingName, Value)
        End Set
    End Property

    Friend Const EmployeeAssociation As String = "CompanyEmployees"
     _
    Public ReadOnly Property Employees() As XPCollection(Of Employee)
        Get
            Return GetCollection(Of Employee)(Fields.Employees.PropertyName)
        End Get
    End Property

    Private Shared fFields As FieldsClass
    Public Shared Shadows ReadOnly Property Fields() As FieldsClass
        Get
            If ReferenceEquals(fFields, Nothing) Then
                fFields = New FieldsClass()
            End If
            Return fFields
        End Get
    End Property
    'Created/Updated: PC-ALF\PC-ALF\Michael 6/10/2010 7:07 AM
    Public Shadows Class FieldsClass
        Inherits DevExpress.Xpo.XPObject.FieldsClass
        Public Sub New()
            MyBase.New()
        End Sub
        Public Sub New(ByVal propertyName As String)
            MyBase.New(propertyName)
        End Sub
        Public ReadOnly Property TradingName() As DevExpress.Data.Filtering.OperandProperty
            Get
                Return New DevExpress.Data.Filtering.OperandProperty(GetNestedName("TradingName"))
            End Get
        End Property
        Public ReadOnly Property Employees() As DevExpress.Data.Filtering.OperandProperty
            Get
                Return New DevExpress.Data.Filtering.OperandProperty(GetNestedName("Employees"))
            End Get
        End Property
    End Class
End Class

Public Class Employee
    Inherits XPObject

    Private fCompany As Company
    
    Public Property Company As Company
        Get
            Return fCompany
        End Get
        Set(ByVal Value As Company)
            SetPropertyValue(Fields.Company.PropertyName, fCompany, Value)
        End Set
    End Property


    Private fFullname As String
    Public Property Fullname As String
        Get
            Return fFullname
        End Get
        Set(ByVal Value As String)
            SetPropertyValue(Fields.Fullname.PropertyName, fFullname, Value)
        End Set
    End Property

    Private Shared fFields As FieldsClass
    Public Shared Shadows ReadOnly Property Fields() As FieldsClass
        Get
            If ReferenceEquals(fFields, Nothing) Then
                fFields = New FieldsClass()
            End If
            Return fFields
        End Get
    End Property
    'Created/Updated: PC-ALF\PC-ALF\Michael 6/10/2010 7:07 AM
    Public Shadows Class FieldsClass
        Inherits DevExpress.Xpo.XPObject.FieldsClass
        Public Sub New()
            MyBase.New()
        End Sub
        Public Sub New(ByVal propertyName As String)
            MyBase.New(propertyName)
        End Sub
        Public ReadOnly Property Company() As XpoSqlIdTest.Company.FieldsClass
            Get
                Return New XpoSqlIdTest.Company.FieldsClass(GetNestedName("Company"))
            End Get
        End Property
        Public ReadOnly Property Fullname() As DevExpress.Data.Filtering.OperandProperty
            Get
                Return New DevExpress.Data.Filtering.OperandProperty(GetNestedName("Fullname"))
            End Get
        End Property
    End Class
End Class

Comments  

 
0 # 2010-10-06 08:45
Another way is to simply use Association attribute without any paramter. for simple 1:n associations no name is needed?
Reply | Reply with quote | Quote
 
 
0 # Michael Proctor [Dx-Squad] 2010-10-06 08:56
Hey Noxe,

Yes that is true, however I believe there is some performance issues with that approach. I haven't researched it heavily nor done any testing however same as SetPropertyValu e the more you use the "generic" overloads the more Reflection is used, as XPO will have to look through the ClassInfo to find out information.

An another example with the Association with the optional Type parameter, you don't have to specify it however if you don't XPO has to use Reflection on the property to get the neccessary details.

To my knowledge these properties can be hit very often in certain operations so the more efficient they are the better.

But again I won't declare that as fact, it is just my understanding of XPO. I would appreciate if anyone has any other information on the topic to let us know.
Reply | Reply with quote | Quote
 
 
+1 # 2010-10-06 09:21
Hey Michael,

i dont think reflection is used here - see MetaData.cs - GetAssociatedMe mber method. It always loops through all members there. I dont know if its best practive what i am doing - i do it to get rid of the association strings :)
Reply | Reply with quote | Quote
 
 
0 # Michael Proctor [Dx-Squad] 2010-10-06 09:58
Hey Martin,

there ya go missed that bit

I made the assumption that like SetPropertyValu e the more information provided reduces Reflection usage, however after your comments and looking at the source I understand now that regardless of the information XPO will have to use Reflection to "verify" the relationship anyway so regardless what you do the end result is the same

So the next question is what is the use case for specifying an Association name... need to look at the code again to see how XPO handles if you have two associations of same types on the same classes, ie. Client.SalesBilled -> Sales.BillTo and Client.Sales -> Sales.Site

One would assume XPO will build an unique association key using the names on both classes, but will have to look into that.

The next thing is specifying the Type for the association, where is that required/recommended? again will have to look at the code.

Might pop DX a question on the support center to get some more info on the Best Practice/Use Cases for those optional params.

Thanks for the heads up, this is something I love about the community, we are all constantly learning every day.
Reply | Reply with quote | Quote
 
 
0 # Michael Proctor [Dx-Squad] 2010-10-15 20:59
Hey bud, logged this support centre request for documentation to be cleaned up. www.devexpress.com/issue=S35947

Found that the type argument in the association is only required if you are not using the generic XPCollection return type, if you are using XPCollection you need to tell XPO what the other side of the relation is, makes sense really but not very clear.

I still haven't found out the exact scenario of when to specify the Name property, I would assume the Best Practice would be to define it, that way if you do add other associations on your object you won't accidentally end up with conflicts. But it isn't a major issue.

Just thought I would let ya know.
Reply | Reply with quote | Quote
 
 
0 # 2010-10-06 16:55
Hey Michael,

you are right - community is a great thing - i also learn every day :)

You are right about multiple associations - in this case i think xpo cannot resolve the correct associations. would be interessting whats the best practice here...
Reply | Reply with quote | Quote
 
 
0 # Michael Proctor [Dx-Squad] 2011-05-10 16:51
For the record if anyone is following this, DevExpress has updated the ticket and implemented it in 10.2.7 and 11.1 help releases.

Just had a look and it explains it much better
documentation.devexpress.com/#XPO/CustomDocument2041
Reply | Reply with quote | Quote
 

Add comment

Although I believe your free to say what you want, please don't abuse either myself or other peoples, be constructive.


Security code
Refresh

Latest Comments

My Twitter

Follow me on twitter