Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are Entity Framework Core conventions?

Tags:

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

like image 927
Macko Avatar asked Oct 19 '17 19:10

Macko


People also ask

What is Entity Framework Convention?

Conventions are a set of rules hard-baked into Entity Framework Core that govern how the model will be mapped to a database schema. Most of the time, especially with new application development, it makes sense to follow EF Core's conventions when developing the model.

Which of the following is the default convention to configure a Primarykey property in EF6 code first?

EF will create a primary key column for the property named Id or <Entity Class Name> + "Id" (case insensitive). By default EF will look for the foreign key property with the same name as the principal entity primary key name.


2 Answers

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

like image 100
Paul Hatcher Avatar answered Sep 18 '22 13:09

Paul Hatcher


Looks like it's still not in EF Core 2.0. So here's one way of achieving it. I had done this to apply consistent behaviour to certain attributes, but to address the examples in your question you could try this:

protected override void OnModelCreating(ModelBuilder modelBuilder) {     // equivalent of modelBuilder.Conventions.AddFromAssembly(Assembly.GetExecutingAssembly());     // look at this answer: https://stackoverflow.com/a/43075152/3419825      // for the other conventions, we do a metadata model loop     foreach (var entityType in modelBuilder.Model.GetEntityTypes())     {         // equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();         entityType.Relational().TableName = entityType.DisplayName();          // equivalent of modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();         // and modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();         entityType.GetForeignKeys()             .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade)             .ToList()             .ForEach(fk => fk.DeleteBehavior = DeleteBehavior.Restrict);     }      base.OnModelCreating(modelBuilder); } 

You should be able to do a lot of things with entityType

like image 34
Balah Avatar answered Sep 16 '22 13:09

Balah