Skip to content

Support of immutable "Owned Entity Types" #11774

Closed as not planned
Closed as not planned

Description

I have the following immutable class:

public class Cost
{
    public decimal PurchasePrice { get;  }
    public decimal EstimatedRetailPrice { get;  }
    public decimal SalesPrice { get;  }

    public Cost() {}

    public Cost(decimal purchasePrice = 0, decimal estimatedRetailPrice = 0, decimal salesPrice = 0)
    {
        PurchasePrice = purchasePrice;
        EstimatedRetailPrice = estimatedRetailPrice;
        SalesPrice = salesPrice;
    }
}

If I just use modelBuilder.Entity<Order>().OwnesOne(x => x.TotalCost) EF won't recognize my readonly properties (TotalCost is of type Cost).

To use my immutable Cost class I wrote the following extension:

public static class EntityTypeBuilderExtensions
{
    /// <summary>
    /// Allows an immutable object to be defined as an 'Owned Entity Type' in EF .
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TRelatedEntity"></typeparam>
    /// <param name="entityTypeBuilder"></param>
    /// <param name="expression"></param>
    public static void OwnsOneImmutable<TEntity, TRelatedEntity>(this EntityTypeBuilder<TEntity> entityTypeBuilder, Expression<Func<TEntity, TRelatedEntity>> expression)
        where TEntity : class
        where TRelatedEntity : class
    {
        var constructor = typeof(TRelatedEntity).GetConstructor(Type.EmptyTypes);
        if (constructor == null)
            throw new InvalidOperationException($"Class '{typeof(TRelatedEntity).Name}' does not contain a parameterless constructor.");

        var builder = entityTypeBuilder.OwnsOne(expression);

        var fieldInfos = typeof(TRelatedEntity).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).ToList();
        var propertyInfos = typeof(TRelatedEntity).GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);

        foreach (var propertyInfo in propertyInfos)
        {
            var fieldInfo = fieldInfos.Single(x => x.Name == $"<{propertyInfo.Name}>k__BackingField");
            builder.Property(propertyInfo.PropertyType, propertyInfo.Name).HasField(fieldInfo.Name);
        }
    }
}

But EF still throws an exception Field '<EstimatedRetailPrice>k__BackingField' of entity type 'Cost' is readonly and so cannot be set.

Please support immutable 'Owned Entity Types'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    closed-no-further-actionThe issue is closed and no further action is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions