Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Fluent API: Set property for each entity derived from a base abstract class

I have a BaseClass, which is abstract, and has many abstract properties.

I have a dozen or so (it will probably grow) entities that are part of the Entity Framework that each derive from BaseClass.

I'm trying to avoid having to do:

modelBuilder.Entity<Entity1>().HasKey(t => t.Id);
modelBuilder.Entity<Entity2>().HasKey(t => t.Id);
modelBuilder.Entity<Entity3>().HasKey(t => t.Id);
...

for each property and each entity, since that seems very wasteful and creates a lot of code duplication. I experimented with getting all the Entities in a namespace that derive from the BaseClass by:

var derivedEntities = Assembly.GetExecutingAssembly().GetTypes().
                Where(t => t.Namespace == "My.Entities" && t.IsAssignableFrom(typeof(BaseClass)));

However, the next logical steps seems to be:

foreach (var entity in derivedEntities)
{
    modelBuilder.Entity<entity>().HasKey(t => t.Id);
}

but will not compile, because

"entity is a variable, but is used like a type".

like image 784
blgrnboy Avatar asked Oct 01 '15 21:10

blgrnboy


People also ask

How do you configure a primary key for an entity in Entity Framework Fluent API?

Configuring a primary key By convention, a property named Id or <type name>Id will be configured as the primary key of an entity. Owned entity types use different rules to define keys. You can configure a single property to be the primary key of an entity as follows: Data Annotations.

Which method is used to apply configuration to entities or their properties in the Entity Framework Core?

Property Mapping. The Property method is used to configure attributes for each property belonging to an entity or complex type.

Does data annotation attributes override Fluent API configuration?

Data annotations and the fluent API can be used together, but Code First gives precedence to Fluent API > data annotations > default conventions. Fluent API is another way to configure your domain classes.

Which is a Fluent API method that can be used to configure a default value for the column that the property maps to?

The Entity Framework Core Fluent API HasDefaultValue method is used to specify the default value for a database column mapped to a property.


1 Answers

I figured it out:

public class BaseObjectConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
        where TEntity : BaseObject
{
        public BaseObjectConfiguration()
        {
            // Mapped
            HasKey(t => t.Id);
            Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(t => t.Name).IsRequired().HasMaxLength(100);
            Property(t => t.DisplayName).IsOptional().HasMaxLength(100);
            Property(t => t.Alias).IsOptional().HasMaxLength(100);
            Property(t => t.SourceId).IsRequired();
            Property(t => t.AccessLevel).IsRequired();
            Property(t => t.CreatedOn).IsOptional();
            Property(t => t.CreatedBy).IsOptional().HasMaxLength(50);
            Property(t => t.ModifiedOn).IsOptional();
            Property(t => t.ModifiedBy).IsOptional().HasMaxLength(50);

            //// Base Entity Ignores (Not Mapped)
            Ignore(t => t.SomeIgnoredProperty);
            Ignore(t => t.SomeIgnoredProperty2);
            Ignore(t => t.SomeIgnoredProperty3);
        }
}

Then, in OnModelCreating inside of the DbContext:

modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity1>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity2>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity3>());
modelBuilder.Configurations.Add(new BaseObjectConfiguration<Entity4>());
...

// Specific mappings options for each entity:
modelBuilder.Entity<Entity1>().HasRequired(t => t.NodeTypeEntity).
                WithMany(t => t.Nodes).HasForeignKey(t => t.NodeTypeId);
            modelBuilder.Entity<NWatchNode>().HasOptional(t => t.Parent).
                WithMany(t => t.Children).HasForeignKey(t => t.ParentId);
...
like image 103
blgrnboy Avatar answered Oct 03 '22 01:10

blgrnboy