I've got a set of immutable POCO objects that reflect database content. These have a one-many relationship:

Property has one PropertyType, which has many PropertyTypeMetadatas.

Because Property has only one PropertyType, and it holds information that is frequently going to be used by the consumers of Property, I've added complexity to my POCO object by integrating it. Property has a reference to PropertyType. Whenever I get one from the database I do a join and build an object with PropertyType present:

class Property
    public PropertyType MyPropertyType;

I'm a little uncomfortable with this. It seems to be 'polluting' the purity of my Property data object adding the relationships to it.

However it's very convenient, as you almost always need to know the PropertyType of a property.

Since I added the PropertyTypeMetadata I'm finding a similar situation. I'm often doing two data access calls with the PropertyTypes, one to get the property, then again to get it's metadata. And again, I often need to access the PropertyTypeMetadata when I'm consuming the Properties - it's often a bit convoluted to get a set of Properties based on a condition, then work out how to get all the Metadata's that relate to them.

As a result I'm starting to consider adding PropertyTypeMetadata as a property of PropertyType and doing the same thing as above.

I figure I've got three options:

  1. Keep my POCO objects 'pure' and super simple. They'd reflect the database tables they represent and little else. It'll be more 'effort' and complexity for the consumer, as they'd have to perform lots of different calls to gather related data as they needed it.
  2. Muddy my 'POCO objects by adding the common relationships, and eager loading and populating these relationships. The POCO objects become more complex, don't reflect the database tables so well. But consuming them is easier as the data you need is to hand. This makes, say, creating or updating an object much messier.
  3. Some kind of hybrid. Maybe I could have the simple POCO objects and wrap them in a more complex type?


interface IProperty {...}
class POCOProperty {...}

interface IPropertyType {...}
class POCOPropertyType {...}

interface IPropertyTypeMetadata {...}
class POCOPropertyTypeMetadata {...}

class PropertyWithRelationships implements IProperty 
    ...passthrough properties to satisfy Property interface

    public POCOProperty Property;
    public PropertyTypeWithRelationships PropertyType ;

class PropertyTypeWithRelationships implements IPropertyType  
    ...passthrough properties to satisfy PropertyType interface

    public POCOPropertyType PropertyType;
    public POCOPropertyTypeMetadata[] Metadata;

My attempt at a diagram:

enter image description here

Example of current (C#, but it shouldnt' matter too much) class:

public class PropertyTypeRecord : IPropertyType
    // as I'm overwriting equals operator as I'm following the convention
    // that immutable types are equal if the data is the same
    private int hashCode;

    public Guid ID { get; private set; }
    public Guid ChangeId { get; private set; }
    public DateTime? ChangeDate { get; private set; }

    public string Name { get; private set; }
    public DataType DataType { get; private set; }
    public UpdateType UpdateType { get; private set; }

    public Guid ElementTypeId { get; private set; }

    public PropertyTypeRecord(Guid id,
                              Guid changeId,
                              DateTime? changeDate,
                              string name,
                              DataType dataType,
                              UpdateType updateType,
                              Guid elementTypeId)
        ID = id;
        ChangeId = changeId;
        ChangeDate = changeDate;
        Name = name;
        DataType = dataType;
        UpdateType = updateType;
        ElementTypeId = elementTypeId;

        hashCode = Hashing.GetStableHashCode($"PropertyTypeRecord{ID}{ChangeId}{ChangeDate}{DataType}{UpdateType}{ElementTypeId}");

    ... Overwriting of equals & gethashcode...
  • why have you got PropertyTypes and Properties instead of public string Name
    – Ewan
    May 4, 2017 at 10:11
  • PropertyTypes aren't just a name. They contain information about how the properties should behave, the data type, and other information etc. A single PropertyType might have lots of Properties of that type. (It's a one-many relationship with one PropertyType having many Properties). They're not class properties, as in C# properties. They're a data construct (I could call them a 'Attributes' and 'AttributeTypes' or something else. It could be 'Users' for the sake of the question).
    – Joe
    May 4, 2017 at 10:16
  • what does it do that a simple Struct with value types doesnt?
    – Ewan
    May 4, 2017 at 10:19
  • In the CRUD case, it's much like a struct - except it's Immutable (I'm not sure you can have immutable structs?). I'll put some example code for one. But making them like that is the 'Option 1' (and 3 maybe). If I go Option 2, then they have to contain references to the other objects.
    – Joe
    May 4, 2017 at 10:21
  • you can make them immutable by making the setters private. They can contain collections of other objects. Your setup seems crazy complex, I dont understand what you are trying to achieve, or what you mean by a CRUD object if not just a POCO
    – Ewan
    May 4, 2017 at 10:24

1 Answer 1


I think this a case of over genericising (if that's a word?)

Delete all your Property, PropertyType, IProperty madness and just make classes that match the table definition. ie

public class Customer
    public string Id;
    public string Name;
    public DateTime DateOfBirth;
    public List<Address> Addresses;

The relationships should either be within the object itself (like addresses) or in the Repository Methods ie

Repo.GetAddressesForCustomerId(string id)
  • I think you're right I'm trying to over think things. I'll decide which to eager-load and which not to and reflect that in the models without any of the complication.
    – Joe
    May 5, 2017 at 9:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.