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 :(
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