postgresqlentity-framework-core.net-6.0entity-framework-migrations

how to set entity's property order to mapping migrations dbscript columns order?


1.I have a BaseModel class:

public class BaseModel : BaseDeletedModel
{
    [Key, Column(Order = 0), MaxLength(50), Required]
    public string ID { get; set; }
}


public class BaseDeletedModel
{
    [Column(Order = 100), DefaultValue(false)]
    public bool IsDeleted { get; set; }
}
  1. and then i create a bussiness class to inherit this base class:
public class Test: BaseModel
{
    [MaxLength(200), Required]
    public string Name { get; set; }
}

3.The script generated by the migration instruction is as follows:

columns: table => new
{
    id = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
    is_deleted = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
   
    name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false)
}

4.but i want the order is: id name isdeleted

I don't want to use the Fluent API to set it up like this:

modelBuilder.Entity<Test>().Property(e => e.ID).HasColumnOrder(0);
modelBuilder.Entity<Test>().Property(e => e.Name).xxxxxxxxxx;
modelBuilder.Entity<Test>().Property(e => e.IsDeleted).HasColumnOrder(100).HasDefaultValue(false);

just set in entity class,is there a good solution?


Solution

  • You can define a custom extension method to sort properties in a specific order for all known entities:

    public static class ModelBuilderExtensions
    {
        public static ModelBuilder ApplyCustomColumnsOrder<TFirst, TLast>(this ModelBuilder modelBuilder)
        {
            var first = typeof(TFirst);
            var last = typeof(TLast);
    
            foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            {
                if (!first.IsAssignableFrom(entityType.ClrType)) 
                    continue;
    
                var typeProperties = entityType.ClrType.GetProperties().ToList();
                var properties = entityType.GetProperties()
                    .Select((prop, index) => (
                        index: prop.PropertyInfo == null ? index * 10000 : typeProperties.IndexOf(prop.PropertyInfo),
                        prop))
                    .ToList();
    
                var sorted = properties
                    .OrderBy(p =>
                        p.prop.PropertyInfo?.DeclaringType == first ? 0 : p.prop?.PropertyInfo?.DeclaringType == last ? 2 : 1)
                    .ThenBy(p => p.index)
                    .Select(x => x.prop)
                    .ToList();
    
                for (var i = 0; i < sorted.Count; i++)
                {
                    sorted[i].SetColumnOrder(i);
                }
            }
    
            return modelBuilder;
        }
    }
    

    In the OnModelCreating method, you should call this extension method at the end of the method:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Other existing configurations
    
        modelBuilder.ApplyCustomColumnsOrder<BaseModel, BaseDeletedModel>();
    }