EF 核心的 HasIndex(Expression<Func<T,object>>) 是否始终使索引排序正确?

Does EF core's HasIndex(Expression<Func<T,object>>) always get the index ordering correct?

据我所知,没有一种可靠的、有记录的方法来按照它们在源文件中声明的顺序获取匿名类型属性,这让我怀疑我是否使用了 EF 核心的 HasIndex因此:

modelBuilder.Entity<T>(entity => entity.HasIndex(e => new { e.Z, e.A }) )

..确定索引将按列顺序 Z,A 创建吗?


我不太关心 params string 重载形式:

modelBuilder.Entity<T>(entity => entity.HasIndex("Z", "A") )

..因为我认为数组元素顺序决定索引列顺序是合乎逻辑的。

我正在努力使用这种形式,但是,没有硬编码字符串,因为 DbSet<X> 是这样定义的:

public virtual DbSet<X> X {get;set;}

..而不是复数 Xs(不是我的规则,但我坚持使用它),所以尝试使用 HasIndex(nameof(X.Z), nameof(X.A)) 是错误的,因为最近的可访问 X 是一个集合的 X,而不是类型 X,因此没有我想要的属性 nameof

我能解决这个问题的最接近方法是实例化一个 X:

modelBuilder.Entity<SessionChargingProfileLog>(entity =>
{
    var x = new X(0, 0, "");

    entity.HasIndex(nameof(x.Z), nameof(x.A)).IsClustered().IncludeProperties(nameof(x.B));

});

..有点..

所以,如果能够具体确认“是的,HasIndex(e => new { e.Z, e.A }) 肯定会创建索引为 Z,A”,那就太棒了;我会测试它,但我不认为“尝试并观察它在这种情况下是否正确”意味着它保证它总是会成功,而不是“是的,它会成功,因为......”

是的,EF 完全按照您定义的相同顺序创建索引。

因为索引中列的顺序在关系数据库中非常重要,所有搜索场景都是按列顺序查找索引(在构建执行计划时)。

如您所知,当更改特定索引的列顺序时,您应该重建该索引以根据新顺序创建。

As far as I'm aware, there isn't a reliable, documented way to get anonymous type properties in the order that they're declared in a source file

您忽略了一个事实,即您在这里不是通过反射在运行时处理匿名类型,而是使用编译时生成的表示匿名类型实例化的表达式树。 lambda 的主体是 NewExpression (not MemberInit as it looks syntactically), which is a constructor call with Arguments containing the defining expressions in the order you specify them and also mapped to Members,这是专门为匿名类型制作的:

The Members property provides a mapping between the constructor arguments and the type members that correspond to those values. In the case of the construction of an anonymous type, this property maps the constructor arguments to the properties that are exposed by the anonymous type. This mapping information is important because the fields that are initialized by the construction of an anonymous type, or the properties that access those fields, are not discoverable through the Constructor or Arguments properties of a NewExpression node.

订单呢,Anonymous Types 的文档说:

If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.

所以既然初始化的顺序是匿名类型标识的一部分,那么它应该由编译器保存,并反过来反映在编译器生成的 lambda 表达式中。