Representing a collection as a Value Object

I was reviewing the list of topic ideas lately and found this question in the discussion to my DDD in Practice Pluralsight course. While I answered it – somewhat briefly – in the discussion thread, I think it’s worth a separate detailed blog post. The question itself goes like this: “Can you have a collection of Value Objects abstracted as a Value Object itself?” Or, in other words, can you represent a collection as a Value Object?

Collection as a Value Object

In the world of DDD, there’s a well-known guideline that you should prefer Value Objects over Entities where possible. If you see that a concept in your domain model doesn’t have its own identity, choose to treat that concept as a Value Object. This approach has a lot of benefits, the most important of which is that Value Objects are much easier to work with. Check out this post to read more about the subject: Entity vs Value Object: the ultimate list of differences.

It’s quite easy to follow this guideline when you deal with single items. For example, if you want to introduce value object City which can be turned on and off for some reason, you can do it like this:

public sealed class City : ValueObject<City>


    public string Name { get; }

    public bool IsEnabled { get; }


    public City(string name, bool isEnabled)


        Name = name;

        IsEnabled = isEnabled;



    protected override bool EqualsCore(City other)


        return Name == other.Name && IsEnabled == other.IsEnabled;



    protected override int GetHashCodeCore()


        return Name.GetHashCode() ^ IsEnabled.GetHashCode();



But what to do if you need to have a collection of such cities? Can the collection itself also be represented as a separate Value Object? And how should we map it to the database in this case?

The common way to deal with collections is to introduce a 1-to-many relation, like this:

public class User : Entity


    public List<City> Cities { get; set; }


The problem, however, is that in order to do that, we need to also create a 1-to-many relationship in the database. In other words, introduce a separate table for cities and bind them together with users using a foreign key constraint:

Collection as a Value Object: A common way of representing a collection

A common way of representing a collection

That, in turn, makes us unable to treat City as a value object. This concept now has its own identifier which makes it effectively an entity. The problem with the common way of working with collections is that we inevitably have to represent items in them as entities if we want to persist those items in a relational data store.

We have to do that even if the items themselves are not entities per se. It becomes quite annoying at times as the number of entities in the model grows, making it more complex than necessary. How are we supposed to follow the guideline in such situation?

Luckily, there is a way. To overcome the problem, you need to introduce a separate class for the whole collection. Here’s how you can do that:

public class CityList : ValueObject<CityList>, IEnumerable<City>


    private List<City> _cities { get; }


    public CityList(IEnumerable<City> cities)


        _cities = cities.ToList();



    protected override bool EqualsCore(CityList other)


        return _cities

            .OrderBy(x => x.Name)

            .SequenceEqual(other._cities.OrderBy(x => x.Name));



    protected override int GetHashCodeCore()


        return _cities.Count;



    public IEnumerator<City> GetEnumerator()


        return _cities.GetEnumerator();



    IEnumerator IEnumerable.GetEnumerator()


        return GetEnumerator();



Note that for CityList, the same rules apply as for any other Value Object. First of all, we need to compare instances of such a list using structural equality. And we do: the EqualsCore method in this example uses SequenceEqual. It goes through each item in two collections and makes sure they match.

CityList must also be immutable. It means that if you want to change an element in it or add a new one, you need to return a new list as a result of that operation:

public CityList AddCity(string name, bool isEnabled)


    List<City> cities = _cities.ToList();

    cities.Add(new City(name, isEnabled));


    return new CityList(cities);


Finally, the collection should not hold an identity of any kind. The easiest way to ensure that is to store the whole list of cities in a single field of the User table. A simple serialization mechanism that converts the list to and from a string would suffice here:

public static explicit operator CityList(string cityList)


    List<City> cities = cityList.Split(‘;’)

        .Select(x => (City)x)



    return new CityList(cities);



public static implicit operator string(CityList cityList)


    return string.Join(“;”, cityList.Select(x => (string)x));


And, to actually persist a list to the data store along with other users’ data, you need to transform it to a string behind the scene, like this:

public class User : Entity


    private string _cities = string.Empty;

    public virtual CityList Cities


        get { return (CityList)_cities; }

        set { _cities = value; }



That string then can be used by ORM. The resulting User row in the database would like the following in this case:

UserID: 1,

CityList: “City1|true;City2|false;”

Collection as a Value Object: drawbacks

This approach helps stick to the guideline regarding preferring Value Objects over Entities and thus keep the domain model simpler. However, there are some shortcomings to this implementation.

The first one is a corollary from the use of the serialization format that helps us persist the list to the database. That is, you would not be able to perform an effective search in such a de-normalized data. That might be just fine if you don’t need to, but if you do, the approach described above wouldn’t fit your situation.

Secondly, if the number of items in the collection tends to be high, treating it as a Value Object wouldn’t be sufficient either. You need to decide where to draw the line yourself, that depends on performance requirements you’ve got to meet. But I would say that a hundred, maybe a couple hundred items is too many for most applications. Serializing them into a single string when persisting the entity would degrade the performance.

In the example above, if a user is about to have 200 cities, I would be reluctant to implement that list as a Value Object.

Finally, this approach is applicable only when you need to store a list of Value Objects, not a list of Entities. The latter would require you to keep references to them in the same manner we did previously:

ListOfEntities: “12;13;15”

And that is just a plain abuse of relational database principles. You wouldn’t be able to enforce referential integrity through the normal database constraints and you would not be able to use ORMs properly.

So, a collection can be a Value Object only when items in it themselves are Value Objects.

Having that said, the question still remains: what are you supposed to do if you do need to search among items in the collection or their number is too high? In such case, treating the items as Entities is the only viable option: you would need to create a separate table for them and deal with the identifier each of them will have after that.

But even in this case, there is a way to bring your code closer to the “Value Objects over Entities” guideline. I’ll write about how to do that in the next post.


Having a collection of items represented as a Value Object is possible. To do that, you need to:

  • Store the whole collection in a single database table field.
  • Come up with a serialization mechanism which would convert the collection from and to a string in order to save it in that field.

There are some drawbacks to that solution, so you need to carefully weigh the pros and cons of this approach. The drawbacks are:

  • You are unable to perform an effective search among individual items in the collection.
  • The approach may hit performance if you’ve got a lot of items in the collection.
  • It is applicable only when items in the collection themselves are also Value Objects.

Related articles:


  • Daris

    You don’t need to have have separate class for persisting collection of value objects.
    JSON will do a trick, you just need to create custom mapping for your ORM.

    Next thing, searching for an value object for example to remove it from collection.
    Don’t make them works as entities, the trick in this one is about creation of VO’s.
    Make one way to create specific VO, by factory method or factory class. Make it returns same reference to Value Objects, which are created with same data.
    In this way you can just create VO on upper layer and pass it to collection to be removed.

    I agree when there is huge amount of VO in collection, this may create a problem. But question here is, if the problem will not be removed by exposing solution like the above? Value object mostly contains like 1-3 properties, so we don’t have much combinations of different VO’s 🙂

    • Vladimir Khorikov

      You don’t need to have have separate class for persisting collection of value objects.
      JSON will do a trick, you just need to create custom mapping for your ORM.

      Persistence of the collection is only part of the problem, really. Another part is that you need to make it follow the Value Object semantics: make it immutable and compare instances of it using its content (most likely without taking into account the order in which items appear in the collection). It’s hard to implement these requirements without introducing a separate class.

      You can still employ JSON serialization, though. Nothing prevents you from doing that with a separate collection class.

  • pbujok

    I also was wondering about this topic. IMHO, approach which you described is good solution if we care only about DDD rules. But on the other hand, it violates fundamental databases’ normalization rules. Please let me know if you think that this is a good way to resolve given problem?

    • Vladimir Khorikov

      Database normalization is a quite common concern, indeed. I don’t think there’s a violation, though. The relationship, should you represent it in the database the same way as in the domain model, would we 1-to-1. It’s safe to merge tables which relate to each other this way. I would even recommend you do that as this approach allows to improve performance due to fewer number of joins.

      Also, DB normalization is often implemented at the expense of simplicity, and that’s not the best trade-off in most cases. Here I showed a case on that topic:

  • Nabil Sedoud

    I think that the principle of identity in DDD, has nothing to do with the notion of primary key of a DB table.
    The primary key is a technical aspect, it can represent an identity such as the number of an invoice. But this is not the case systematically.
    As a reference to an instance of class does not necessarily represent an identity.

    • Vladimir Khorikov

      The primary key is indeed a technical aspect but it fits well the notion of identity in DDD. There’s a rule of thumb regarding DB primary keys stating that you shouldn’t use natural keys for them (like invoice number), only surrogate ones (like GUID or auto-increment integers). If you follow this rule, then you can say that the primary key represents an entity’s identity.

      The reason why is because an identity cannot be tracked to any particular property of the entity. It’s a “virtual” substance, so to speak. So is a surrogate primary key. It doesn’t represent any “real” data in the table.

  • Niklas Engberg

    Hello Vladimir and thanks for another great post. I came across your blog a while back ago and I must say that your posts (and your Pluralsight courses) are very good.

    To my question: I cannot seem to get this to work with EF Core 2.1. I know that they do not support collections of owned entity types (yet) but thought that this approach that you’ve demonstrated would work.

    Have you tried this with EF Core? If you have, it would be interesting to see a full working example 🙂

    Best regards

  • Mher Sargsyan

    Hi Vladimir.

    Consider this example.

    Aggregate Root: ProductionOrder identified by order code.

    Each production order in my domain model can have multiple files associated to it.
    (Actually there are order lines in each order which are local entities but I will skip that part for brevity). In this case we have a relationship one to many. I can even say it’s a one to some relationship as each order can not have more than 5 files.

    In order to implement this I came up with two VOs
    1. File : properties name, type
    2. FileConsumption: property Collection

    In my model there is no conceptual identity for files so if file name and file type matches I can easily treat two objects as same and use interchangeably.

    In order to persist this in sql database I decided to have private encapsulated surrogate id for a File VO but it is never used and never visible for a client code. Additionally equals and hashcode methods just ignore existence of surrogate id.

    In the end code looks like

    class ProductionOrder {
    private FileConsumption fileCons;

    class FileConsumption {
    private Collection files;
    boolean equals(FileConsumption other) {

    int hashcode() {.. the same way}

    class File {
    private String name;
    private String type;

    boolean equals(File other) {
    && this.type.equals(other.type)

    int hashcode() {.. the same way}


    Do you think this is a valid approach?

    • Vladimir Khorikov

      It would recommend not to fight the relational database and the ORM (assuming you use one, if not, your approach is fine as you need to implement the O/R mapping manually anyway). A simpler solution would be to create a standard one-to-many relationship between Order and File entities. Create a VO that is hosted inside File ( refer to this article for more details ), and then expose a collection of value objects from Order. Something like this:

      class ProductionOrder {
      private IList _orderFiles; // entities
      public IList Files => _orderFiles.Select(x => x.File).ToList(); // VOs

  • alireza Rahmani khalili

    I think value object is a pure function, then when we use something like database(that might change) how we can grantee always with same input we get same out put?

  • Rock Anthony Johnson

    Hi Vladimir,

    Should commands and queries be treated as value objects?

    • Vladimir Khorikov

      Yes. Although, you shouldn’t have any use cases where you need to compare them to each other.

  • corneliu

    Hi Vladimir, I’m trying to do this in NHibernate, but it fails stating that It cannot convert from Object to String. I’m trying a far easier mapping. with CityList having a string property and that is all.

  • Egi

    You can also treat the classes that are known to the ORM as DTOs and keep the Domain Model perfectly clean while also keeping the relational DB normalized. The tradeoff is of course another mapping layer on top of the ORM with all its pros and cons and the fact that you lose some convenience that the ORM provides. I have no opinion yet on which solution I’d prefer.