Hasta donde yo sé, no hay una forma confiable y documentada de obtener propiedades de tipo anónimo en el orden en que se declaran en un archivo fuente, lo que hace que me pregunte si uso el HasIndex de EF core:
modelBuilder.Entity<T>(entity => entity.HasIndex(e => new { eZ, eA }) )... ¿es seguro que el índice se creará en el orden de las columnas Z,A?
Estoy menos preocupado por el formulario de sobrecarga params string :
modelBuilder.Entity<T>(entity => entity.HasIndex("Z", "A") )..porque me imagino que sería lógico que el orden de los elementos de la matriz dictara el orden de las columnas del índice.
Sin embargo, tengo dificultades para usar este formulario sin cadenas codificadas porque DbSet<X> se define así:
public virtual DbSet<X> X {get;set;} ..en lugar de las Xs plurales (no es mi regla, pero me quedo con ella), por lo que tratar de usar HasIndex(nameof(XZ), nameof(XA)) es un error porque la X accesible más cercana es una colección de X , en lugar de escribir X, y por lo tanto no tiene las propiedades que quiero nameof
Lo más cerca que he podido llegar a solucionar este problema es instanciar una X:
modelBuilder.Entity<SessionChargingProfileLog>(entity => { var x = new X(0, 0, ""); entity.HasIndex(nameof(xZ), nameof(xA)).IsClustered().IncludeProperties(nameof(xB)); });..que es un poco..
Entonces, si pudiera confirmarse concretamente que "sí, HasIndex(e => new { eZ, eA }) definitivamente creará el índice como Z, A", sería maravilloso; Lo probaría, pero no creo que "pruébelo y observe si es correcto en este caso" significa que garantiza que siempre funcionará, en lugar de un "sí, funcionará porque..."
Hasta donde yo sé, no existe una forma documentada y confiable de obtener propiedades de tipo anónimo en el orden en que se declaran en un archivo fuente.
Te estás perdiendo el hecho de que aquí no estás tratando con un tipo anónimo en tiempo de ejecución a través de la reflexión, sino con un árbol de expresión generado en tiempo de compilación que representa la creación de instancias de tipo anónimo. El cuerpo de la lambda es NewExpression (no MemberInit como se ve sintácticamente), que es una llamada de constructor con argumentos que contienen las expresiones de definición en el orden en que las especifica y también se asignan a los miembros , que se hace específicamente para tipos anónimos:
La propiedad
Membersproporciona una asignación entre los argumentos del constructor y los miembros de tipo que corresponden a esos valores. En el caso de la construcción de un tipo anónimo, esta propiedad asigna los argumentos del constructor a las propiedades expuestas por el tipo anónimo. Esta información de asignación es importante porque los campos que se inicializan mediante la construcción de un tipo anónimo, o las propiedades que acceden a esos campos, no se pueden detectar a través de las propiedadesConstructoroArgumentsde un nodoNewExpression.
¿Qué pasa con el pedido, la documentación para tipos anónimos dice:
Si dos o más inicializadores de objetos anónimos en un ensamblado especifican una secuencia de propiedades que están en el mismo orden y que tienen los mismos nombres y tipos, el compilador trata los objetos como instancias del mismo tipo. Comparten la misma información de tipo generada por el compilador.
Entonces, dado que el orden de la inicialización es parte de la identidad de tipo anónimo, el compilador debe conservarlo y, a su vez, reflejarlo en la expresión lambda generada por el compilador.
Sí, EF crea el índice en el mismo orden que definiste, exactamente.
Porque el orden de las columnas en el índice es muy importante en las bases de datos relacionales y todos los escenarios de búsqueda están en el orden de las columnas para los índices de búsqueda (cuando se construye el plan de ejecución).
Como sabe, cuando cambia el orden de las columnas para un índice específico, debe reconstruir ese índice para crearlo en función del nuevo orden.