EF6.1から、プロパティにクラスター化インデックスを指定する方法があります
public class Person
{
[Index(IsClustered = true, IsUnique = true)]
public long UserName { get; set; }
}
しかし、このインデックス属性は現在EFコアに含まれていないようです。 EF Coreでは、これをどのように達成しますか?
現在のEFCoreドキュメントから- Indexes section:
データ注釈
データ注釈を使用してインデックスを作成することはできません。
ただし、Fluent APIを介して指定することはできます(SQLServer固有の機能を示しているように見えるForSqlServer
プレフィックスを持つ拡張メソッドに注意してください)。
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.ForSqlServerIsClustered();
組み込みのサポートがない場合は、独自のカスタム属性を使用してモデルプロパティに注釈を付け、OnModelCreating()
に適用できます。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo.GetCustomAttribute<IndexAttribute>();
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = attr.IsUnique;
index.SqlServer().IsClustered = attr.IsClustered;
}
}
}
}
単純なマーカー属性クラスの場合:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IndexAttribute : Attribute
{
public bool IsUnique { get; set; }
public bool IsClustered { get; set; }
}
次に、モデルクラスで、属性を追加してセカンダリインデックスを作成します。
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true, IsClustered = true)]
public string Nickname { get; set; }
}
EF Core3.0以降の場合IsClusteredを使用できるようになりました。
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
.ForSqlServerIsClustered()は廃止としてマークされるようになりました。
また、テーブルに主キーがある場合は、ユーザー名にクラスタリングを追加する前に、そのクラスターを明示的に削除する必要がある場合もあることに注意してください。
modelBuilder.Entity<Person>()
.HasKey(e => e.PersonId)
.IsClustered(false);
modelBuilder.Entity<Person>()
.HasIndex(e => e.UserName)
.IsUnique()
.IsClustered();
または、これも機能します。たとえば、年齢別にクラスター化する場合は...
modelBuilder
.Entity<Person>()
.Property(t => t.Age)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsClustered = true}));