Where are Entity Framework Core conventions?

c# entity-framework-core

Question

using EF 6.1+ there were times where we need to add or remove existing conentions. The code looks more or less like:

public class MyContext : DbContext
    {
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.AddFromAssembly(Assembly.GetExecutingAssembly());
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
                modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
                modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

                base.OnModelCreating(modelBuilder);
            }
}

how do the same in EF core? Modelbuilder has no Conventions property :(

1
17
10/19/2017 7:37:02 PM

Popular Answer

I'm porting some code from EF to EF Core 2.1+ and can't wait for EF Core 3.0 so wrote a few extension methods which help a bit..

public static IEnumerable<IMutableEntityType> EntityTypes(this ModelBuilder builder)
{
    return builder.Model.GetEntityTypes();
}

public static IEnumerable<IMutableProperty> Properties(this ModelBuilder builder)
{
    return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties());
}

public static IEnumerable<IMutableProperty> Properties<T>(this ModelBuilder builder)
{
    return builder.EntityTypes().SelectMany(entityType => entityType.GetProperties().Where(x => x.ClrType == typeof(T)));
}

public static void Configure(this IEnumerable<IMutableEntityType> entityTypes, Action<IMutableEntityType> convention)
{
    foreach (var entityType in entityTypes)
    {
        convention(entityType);
    }
}

public static void Configure(this IEnumerable<IMutableProperty> propertyTypes, Action<IMutableProperty> convention)
{
    foreach (var propertyType in propertyTypes)
    {
        convention(propertyType);
    }
}

with these you can write conventions similar to those in EF 6.1.x, for example.

// equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.EntityTypes()
            .Configure(et => et.Relational().TableName = et.DisplayName());

// Put the table name on the primary key
modelBuilder.Properties()
            .Where(x => x.Name == "Id")
            .Configure(p => p.Relational().ColumnName = p.DeclaringEntityType.Name + "Id");

// Mark timestamp columns as concurrency tokens
modelBuilder.Properties()
            .Where(x => x.Name == "Timestamp")
            .Configure(p => p.IsConcurrencyToken = true);

For EF Core 3.0 the metamodel methods have changed slightly so you need

modelBuilder.EntityTypes()
            .Configure(et => et.SetTableName(et.DisplayName()));

modelBuilder.Properties()
            .Where(x => x.Name == "Id")
            .Configure(p => p.SetColumnName(BaseName(p.DeclaringEntityType.Name) + "Id"));

Haven't checked this for efficiency but unless your model is huge it shouldn't pose a problem

This can be extended with other helpers for foreign keys, indexes etc

15
10/31/2019 10:20:53 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow