Question

  1. Here is what I am currently doing:

    modelBuilder.Entity<Product>().Property(e => e.Name).IsRequired();                   
    modelBuilder.Entity<Product>().Property(e => e.UPC).IsRequired();      
    modelBuilder.Entity<Product>().Property(e => e.Price).IsRequired();      
    modelBuilder.Entity<Product>().Property(e => e.Description).IsRequired();
    
  2. Here is what I would like to be doing:

    modelBuilder.Entity<Product>()
        .Property(e => e.Name).IsRequired()
        .Property(e => e.UPC).IsRequired()
        .Property(e => e.Price).IsRequired()
        .Property(e => e.Description).IsRequired()
    

The latter, though, doesn't work. Is there another way not to have to repeat the modelBuilder.Entity<Product>() each time?

  1. Here is the current most pithy option:

    var e = modelBuilder.Entity<Product>();
    e.Property(e => e.Name).IsRequired();                   
    e.Property(e => e.UPC).IsRequired();      
    e.Property(e => e.Price).IsRequired();      
    e.Property(e => e.Description).IsRequired();
    
Was it helpful?

Solution

This is compatible with all of the existing DbModelBuilder extension methods since it's just adding a fluent layer on top, but that it does come with some syntactical overhead. Not exactly what you asked for, but doesn't involve mucking around with the supporting code. Haven't fully tested this yet, but it should work if you're comfortable with the syntax:

// First option - like this better because it has less cruft than multiple Has invocations

var modelBuilder = new DbModelBuilder();
var modelConfiguration = new ModelConfigurator(modelBuilder);

modelConfiguration.Entity<Product>().Has(e => {
                                         e.Property(en => en.Name).IsRequired();
                                         e.Property(en => en.UPC).IsRequired();
                                         e.Property(en => en.Price).IsRequired();
                                         e.Property(en => en.Description).IsRequired();}
                                        );           

OR

var modelBuilder = new DbModelBuilder();
var modelConfiguration = new ModelConfigurator(modelBuilder);
modelConfiguration.Entity<Product>().Has(e => e.Property(en => en.Name).IsRequired())
                                    .Has(e => e.Property(en => en.UPC).IsRequired())
                                    .Has(e => e.Property(en => en.Price).IsRequired())
                                    .Has(e => e.Property(en => en.Description).IsRequired());

// continue configuring properties, and creating methods on ModelConfigurator as needed

Supporting code:

  public class Product{
        public string Name {get;set;}
        public double Price {get;set;}
        public string UPC {get;set;}
        public string Description {get;set;}

    }

    public class ModelConfigurator{

        public DbModelBuilder ModelBuilder{get;set;}

        public ModelConfigurator(DbModelBuilder modelBuilder){
            ModelBuilder = modelBuilder;
        }

        public EntityConfigurator<TEntity> Entity<TEntity>() where TEntity : class {
            var entity = ModelBuilder.Entity<TEntity>();
            return new EntityConfigurator<TEntity>(entity);
        }
    }

    public class EntityConfigurator<TEntity> where TEntity : class{

        public EntityTypeConfiguration<TEntity> EntityTypeConfiguration {get;set;}

        public EntityConfigurator(EntityTypeConfiguration<TEntity> entityTypeConfiguration){
            EntityTypeConfiguration = entityTypeConfiguration;
        }

        public EntityConfigurator<TEntity> Has(Action<EntityTypeConfiguration<TEntity>> a){
            a(this.EntityTypeConfiguration);
            return this;
        }
    }

OTHER TIPS

Another option, no real need for Has() on top of Entity():

modelConfiguration.Entity<Product>(e => {
                                   e.Property(en => en.Name).IsRequired();
                                   e.Property(en => en.UPC).IsRequired();
                                   e.Property(en => en.Price).IsRequired();
                                   e.Property(en => en.Description).IsRequired();}
                                  );

Extension method:

public static EntityTypeConfiguration<TEntity> Entity<TEntity>(this DbModelBuilder modelBuilder, Action<EntityTypeConfiguration<TEntity>> action) where TEntity : class
{
    var r = modelBuilder.Entity<TEntity>();
    action(r);
    return r;
}

I adapted jnm2's answer for EF Core:

public static class ModelBuilderExtensions
{
    public static EntityTypeBuilder<T> Entity<T>(
        this ModelBuilder modelBuilder,
        Action<EntityTypeBuilder<T>> action) where T : class
    {
        var e = modelBuilder.Entity<T>();
        action(e);
        return e;
    }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>(b =>
    {
        b.Property(e => e.Name).IsRequired();
        b.Property(e => e.UPC).IsRequired();
        b.Property(e => e.Price).IsRequired();
        b.Property(e => e.Description).IsRequired();}
    });
}

I guess you can do the following, although I think this is rather awkward.

public static class EntityConfigExtensions
{
    public static EntityTypeConfiguration<TEntity> Prop<TEntity, TProp>(this EntityTypeConfiguration<TEntity> self, Expression<Func<TEntity, TProp>> propExpression) where TEntity : class
    {
        self.Property(propExpression);
        return self;
    }
    public static EntityTypeConfiguration<TEntity> RequiredProp<TEntity, TProp>(this EntityTypeConfiguration<TEntity> self, Expression<Func<TEntity, TProp>> propExpression) where TEntity : class
    {
        self.Property(propExpression).IsRequired();
        return self;
    }
    // etcetera for other frequently used configs
    // ...
    // And, borrowing from David: a catch-all for the rest
    public static EntityTypeConfiguration<TEntity> Configure<TEntity, TProp>(this EntityTypeConfiguration<TEntity> self, Action<EntityTypeConfiguration<TEntity>> configAction) where TEntity : class
    {
        configAction(self);
        return self;
    }
}

Usage:

modelBuilder.Entity<Product>()
    .Prop(e => e.Name)
    .RequiredProp(e => e.UPC)
    .RequiredProp(e => e.Price)
    .Configure(x => x.Ignore(e => e.Description));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top