Davide De Santis
Davide De Santis

Reputation: 1034

EF Core Code First: Generally rename properties of owned types

Following this documentation, I am trying to create some entities with properties of an owned type:

[Owned]
public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public StreetAddress BillingAddress { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

By convention, EF will create the following properties in the entity Order:

BillingAddress_Street  
BillingAddress_City  
ShippingAddress_Street  
ShippingAddress_City

I know that there is a way to rename the columns:

modelBuilder.Entity<Order>().OwnsOne(
    o => o.ShippingAddress,
    sa =>
    {
        sa.Property(p => p.Street).HasColumnName("ShipsToStreet");
        sa.Property(p => p.City).HasColumnName("ShipsToCity");
    });

however, this means that I would need to use this for every property that will be generated. In my opinion, this is exactly what I wanted to avoid by using the owned types in the first place.

What I would like to do, is to create a custom convention, however, maybe using the model builder and explicitly telling him how to name those properties getting rid of the underscore and so on.

I have tried dvelving into the modelBuilder properties, trying to get all of all entities of that owned type, but that does not seem to work.

Is there a way to solve this?

Upvotes: 1

Views: 1028

Answers (1)

Davide De Santis
Davide De Santis

Reputation: 1034

So I could not sleep and went back to trying, and was able to solve it:

var ownedTypes = modelBuilder.Model.GetEntityTypes().Where(e => e.IsOwned());
    foreach (var type in ownedTypes)
    {
        foreach (var prop in type.GetProperties())
        {
            var entityName = type.DefiningEntityType.Name;
            var ownedType = type.ClrType;
            var navigationName = type.DefiningNavigationName;
            var propertyName = prop.Name;
            var newColumnName = $"{navigationName}{propertyName}";

            var primaryKeyName = modelBuilder.Model.GetEntityTypes().SingleOrDefault(e => e.Name == entityName)?.GetProperties().SingleOrDefault(p => p.IsPrimaryKey())?.Name;

            if (string.IsNullOrWhiteSpace(primaryKeyName) || propertyName != primaryKeyName)
            {
                modelBuilder.Entity(entityName).OwnsOne(ownedType, navigationName, sa =>
                {
                    sa.Property(propertyName).HasColumnName(newColumnName);
                });
            }
        }
    }

I would still be glad if you could point me to a better, cleaner solution, should there be one. Or maybe there are some issues here in my code.

Upvotes: 2

Related Questions