M. Koch
M. Koch

Reputation: 822

EF Core - ValueConverter or OwnedType for simple ValueObjects?

I use value objects to encapsulate validations like maxLength. This is an extract of a sample class without factory method and validation:

public class CallingName : ValueObject
{
    public string Value { get; }
    public const int MaxLength = 50;

    private CallingName(string text)
    {
        Value = text;
    }
   ...
 }

In the SQL database the table should have a field 'CallingName' of type nvarchar with a maximum length of 50.

Using EF Core I'm aware of value converters and owned types, but I don't fully understand the options and differences between both. If a value object has only one property, is it possible to use either one?

So far I used a value converter for the field:

entity.Property(e => e.CallingName)
    .HasMaxLength(CallingName.MaxLength)
    .HasConversion(DBConverter.CallingNameConverter);

Looking at the simple example in the Microsoft docs I would think that this should work without a value converter like this

entity.OwnsOne(e => e.CallingName)
     .Property(e => e.Value)
     .HasColumnName("CallingName")
     .HasMaxLength(CallingName.MaxLength);

or

entity.OwnsOne(e => e.CallingName, 
     p=>p.Property<string>("CallingName")
     .HasMaxLength(CallingName.MaxLength));

or

entity.OwnsOne(e => e.CallingName, 
     p => p.Property(e=>e.Value)
    .HasColumnName("CallingName")
    .HasMaxLength(CallingName.MaxLength));

Do all of the above version work? What is the purpose of the different versions? What are the cases or criteria to use a value converter or an owned type?

To my understanding, when types have no public setters they need an empty constructor for owned types. Value converters can call the constructor, resp. the factory method. Is that correct?

The documentation for OwnsOne shows 6 overloads, but has no examples. The descriptions sound Klingon to me. I don't understand what each one is for. I couldn't find any better explantion or article googling. Is there a good explanation with examples?

Upvotes: 2

Views: 1292

Answers (2)

Eltin
Eltin

Reputation: 11

Microsoft said:

It was previously the team view that owned entities, intended for aggregate support, would also be a reasonable approximation to value objects. Experience has shown this not to be the case. Therefore, in EF8, we plan to introduce a better experience focused on the needs of value objects in domain-driven design. This approach will be based on value converters rather than owned entities.

Therefore, I think we should switch to value converters. I personalny used Owned Types, but it is super hard to make multi column unique index using owned types value objects. So I will also switch to converters.

Upvotes: 1

M. Koch
M. Koch

Reputation: 822

I posted the question also in dotnet core issues on github. ajcvickers answered:

Owned types are entity types that have a key property and are identified by the value of that key. (EF may hide this key value from you, but it is still there and affects the semantics of the how the objects are used.) In DDD terms, they are intended to support aggregates, with the owner acting as the aggregate root. They do not work very well for DDD value objects since they are identified by a key, which goes against the principle of value objects.

Using a value converter means that the property is still mapped as a property, and does not have a key. This means that properties with a value converter inherently have value object semantics, and so are a much better fit than owned types.

To my understanding Owned Types are still the only option for value objects with more than one property until EF Core 7.

I still haven't found explantions of the OwnsOne overloads and why to use each one.

Upvotes: 1

Related Questions