Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the difference between ValueConverter or OwnedType for simple value objects? #27758

Closed
KillerBoogie opened this issue Apr 5, 2022 · 3 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@KillerBoogie
Copy link

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?

Include provider and version information

EF Core version:
Microsoft.EntityFrameworkCore.SqlServer
.NET 6

@ajcvickers
Copy link
Member

@KillerBoogie 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.

@KillerBoogie
Copy link
Author

KillerBoogie commented Apr 6, 2022

Thank you for that clear description! To my understanding Owned Types are the only option for value objects with more than one property until EF Core 7.

Do you know of any explantion of the OwnsOne overloads and why to use each one?

@ajcvickers
Copy link
Member

@KillerBoogie They generally all do the same thing, but take different forms of parameters, and optionally allow a delegate for further configuration. Examples are provided in the conceptual docs for owned types.

@ajcvickers ajcvickers added the closed-no-further-action The issue is closed and no further action is planned. label Apr 19, 2022
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

2 participants