EF Core Mapping EntityTypeConfiguration

后端 未结 15 1231
花落未央
花落未央 2020-11-30 18:26

In EF6 we usually able to use this way to configure the Entity.

public class AccountMap : EntityTypeConfiguration
{
    public AccountMap()
           


        
相关标签:
15条回答
  • 2020-11-30 18:53

    Since EF Core 2.0 there is IEntityTypeConfiguration<TEntity>. You can use it like this:

    class CustomerConfiguration : IEntityTypeConfiguration<Customer>
    {
      public void Configure(EntityTypeBuilder<Customer> builder)
      {
         builder.HasKey(c => c.AlternateKey);
         builder.Property(c => c.Name).HasMaxLength(200);
       }
    }
    
    ...
    // OnModelCreating
    builder.ApplyConfiguration(new CustomerConfiguration());
    

    More on this and other new features introduced in 2.0 can be found here.

    0 讨论(0)
  • 2020-11-30 18:53

    In EF7, you override OnModelCreating on the DbContext class you're implementing.

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<Account>()
                .ForRelational(builder => builder.Table("Account"))
                .Property(value => value.Username).MaxLength(50)
                .Property(value => value.Email).MaxLength(255)
                .Property(value => value.Name).MaxLength(255);
        }
    
    0 讨论(0)
  • 2020-11-30 18:53

    I ended with this solution:

    public interface IEntityMappingConfiguration
    {
        void Map(ModelBuilder b);
    }
    
    public interface IEntityMappingConfiguration<T> : IEntityMappingConfiguration where T : class
    {
        void Map(EntityTypeBuilder<T> builder);
    }
    
    public abstract class EntityMappingConfiguration<T> : IEntityMappingConfiguration<T> where T : class
    {
        public abstract void Map(EntityTypeBuilder<T> b);
    
        public void Map(ModelBuilder b)
        {
            Map(b.Entity<T>());
        }
    }
    
    public static class ModelBuilderExtenions
    {
        private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
        {
            return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
        }
    
        public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
        {
            var mappingTypes = assembly.GetMappingTypes(typeof (IEntityMappingConfiguration<>));
            foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>())
            {
                config.Map(modelBuilder);
            }
        }
    }
    

    Sample Use:

    public abstract class PersonConfiguration : EntityMappingConfiguration<Person>
    {
        public override void Map(EntityTypeBuilder<Person> b)
        {
            b.ToTable("Person", "HumanResources")
                .HasKey(p => p.PersonID);
    
            b.Property(p => p.FirstName).HasMaxLength(50).IsRequired();
            b.Property(p => p.MiddleName).HasMaxLength(50);
            b.Property(p => p.LastName).HasMaxLength(50).IsRequired();
        }
    }
    

    and

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly);
    }
    
    0 讨论(0)
  • 2020-11-30 18:54

    In Entity Framework Core 2.0:

    I took Cocowalla's answer and adapted it for v2.0:

        public static class ModelBuilderExtenions
        {
            private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
            {
                return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
            }
    
            public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
            {
                // Types that do entity mapping
                var mappingTypes = assembly.GetMappingTypes(typeof(IEntityTypeConfiguration<>));
    
                // Get the generic Entity method of the ModelBuilder type
                var entityMethod = typeof(ModelBuilder).GetMethods()
                    .Single(x => x.Name == "Entity" &&
                            x.IsGenericMethod &&
                            x.ReturnType.Name == "EntityTypeBuilder`1");
    
                foreach (var mappingType in mappingTypes)
                {
                    // Get the type of entity to be mapped
                    var genericTypeArg = mappingType.GetInterfaces().Single().GenericTypeArguments.Single();
    
                    // Get the method builder.Entity<TEntity>
                    var genericEntityMethod = entityMethod.MakeGenericMethod(genericTypeArg);
    
                    // Invoke builder.Entity<TEntity> to get a builder for the entity to be mapped
                    var entityBuilder = genericEntityMethod.Invoke(modelBuilder, null);
    
                    // Create the mapping type and do the mapping
                    var mapper = Activator.CreateInstance(mappingType);
                    mapper.GetType().GetMethod("Configure").Invoke(mapper, new[] { entityBuilder });
                }
            }
    
    
        }
    

    And it's used in the DbContext like this:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly);
        }
    

    And this is how you create an entity type configuration for an entity:

        public class UserUserRoleEntityTypeConfiguration : IEntityTypeConfiguration<UserUserRole>
        {
            public void Configure(EntityTypeBuilder<UserUserRole> builder)
            {
                builder.ToTable("UserUserRole");
                // compound PK
                builder.HasKey(p => new { p.UserId, p.UserRoleId });
            }
        }
    
    0 讨论(0)
  • 2020-11-30 19:02

    Am I right?

    public class SmartModelBuilder<T> where T : class         {
    
        private ModelBuilder _builder { get; set; }
        private Action<EntityTypeBuilder<T>> _entityAction { get; set; }
    
        public SmartModelBuilder(ModelBuilder builder, Action<EntityTypeBuilder<T>> entityAction)
        {
            this._builder = builder;
            this._entityAction = entityAction;
    
            this._builder.Entity<T>(_entityAction);
        }
    }   
    

    I can Pass config:

     protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            // Customize the ASP.NET Identity model and override the defaults if needed.
            // For example, you can rename the ASP.NET Identity table names and more.
            // Add your customizations after calling base.OnModelCreating(builder);
    
    
    
            new SmartModelBuilder<Blog>(builder, entity => entity.Property(b => b.Url).Required());
    
        } 
    
    0 讨论(0)
  • 2020-11-30 19:06

    This is using current latest, beta 8. Try this:

    public class AccountMap
    {
        public AccountMap(EntityTypeBuilder<Account> entityBuilder)
        {
            entityBuilder.HasKey(x => x.AccountId);
    
            entityBuilder.Property(x => x.AccountId).IsRequired();
            entityBuilder.Property(x => x.Username).IsRequired().HasMaxLength(50);
        }
    }
    

    Then in your DbContext:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            new AccountMap(modelBuilder.Entity<Account>());
        }
    
    0 讨论(0)
提交回复
热议问题