2017-02-12 2 views
5

異なるインデックスタイプのカスタムインデックスおよびキー規則を作成する方法。私は、次のキーまたはインデックスのタイプの異なる命名必要があります。EF6の一意のインデックス規約

  • PK_TableName主キー
  • 外部キー
  • IX_TableName_Column1_Column2非ユニークインデックスの
  • FK_SourceTable_Column_TargetTable
  • UX_TableName_Column1_Column2をユニークインデックス
デフォルトによって

は、Entity Frameworkのは、以下の、ネーミング・使用しています:

  • PK_ のSchemaNameを外部キー
  • のための主キー
  • FK_ のSchemaName .SourceTable_ のSchemaName .TargetTable_Column1ため .TableName
  • IX_Column1ユニークでないインデックスの場合一意索引

ため

  • ColumnNameに私はIStoreModelConvention<T>を実装できることが判明しましたが、私は型パラメータとして使用する特定のタイプを発見していません。 さらに、Custom Code-First Conventionsがあるかもしれませんが、私の研究は結果なしで終了します。エンティティフレームワークを使用するときに、どのように名前付け規則を記述できるのですかコードFirst?それは、パッケージ、サンプル、または次の研究のためのちょうど方向であることができます。

  • +0

    のhttp:/ /stackoverflow.com/questions/22618237/how-to-create-index-in-entity-framework-6-2-with-code-first –

    +0

    ここからご覧いただけます:http://stackoverflow.com/a/18245172/ 5311735 IStoreModelConventionを使用して外部キー名を変更する方法の例。おそらく他のインデックス名もこのように変更できます。 – Evk

    +0

    私は試しましたが、成功しませんでした。私もカスタムSQLジェネレータを試してみました。しかし、情報の不足のために、私は結果がありません –

    答えて

    4

    PKとFKではミッションができません。問題は、ストア制約を命名するための特別なEdmModelプロパティ/属性/アノテーションがないことです。モデルでは、基本的に列(プロパティ)のリストとして表され、命名規則はマイグレーションビルダクラス内でハードコードされます。コメントに記載されているいくつかの例は、FK制約自体ではなく、FK 列(プロパティ)の名前を変更する方法を示しています。

    幸運にもインデックス用ですが、単純ではありませんが、IndexAttributeIndexAnnotationのおかげで可能です。これは、アノテーション(属性付き)が列(エンティティプロパティ)に関連付けられ、ConsolidatedIndexという内部クラスによって統合されているためです。

    IStoreModelConvention<EntityType>を作成し、ConsolidatedIndexクラスのようなプロパティから統合インデックス情報を準備し、名前のないインデックスまたはインデックスのルールに基づいて新しい名前を決定する必要がありますForeignKeyIndexConventionによってFK制約に対して生成され、対応するIndexAnnotationのプロパティを更新します。それは言われていると

    は、ここにあなたのインデックス名規則を適用するためのコードは次のとおりです。

    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel.DataAnnotations.Schema; 
    using System.Data.Entity.Core.Metadata.Edm; 
    using System.Data.Entity.Infrastructure; 
    using System.Data.Entity.Infrastructure.Annotations; 
    using System.Data.Entity.Migrations.Model; 
    using System.Data.Entity.ModelConfiguration.Conventions; 
    using System.Linq; 
    
    public class IndexNameConvention : IStoreModelConvention<EntityType> 
    { 
        public void Apply(EntityType item, DbModel model) 
        { 
         // Build index info, consolidating indexes with the same name 
         var indexInfo = new List<IndexInfo>(); 
         foreach (var p in item.Properties) 
         { 
          foreach (var mp in p.MetadataProperties) 
          { 
           var a = mp.Value as IndexAnnotation; 
           if (a == null) continue; 
           foreach (var index in a.Indexes) 
           { 
            var info = index.Name != null ? indexInfo.FirstOrDefault(e => e.Name == index.Name) : null; 
            if (info == null) 
            { 
             info = new IndexInfo { Name = index.Name }; 
             indexInfo.Add(info); 
            } 
            else 
            { 
             var other = info.Entries[0].Index; 
             if (index.IsUnique != other.IsUnique || index.IsClustered != other.IsClustered) 
              throw new Exception("Invalid index configuration."); 
            } 
            info.Entries.Add(new IndexEntry { Column = p, Annotation = mp, Index = index }); 
           } 
          } 
         } 
         if (indexInfo.Count == 0) return; 
         // Generate new name where needed 
         var entitySet = model.StoreModel.Container.EntitySets.First(es => es.ElementType == item); 
         foreach (var info in indexInfo) 
         { 
          var columns = info.Entries.OrderBy(e => e.Index.Order).Select(e => e.Column.Name); 
          if (info.Name == null || info.Name == IndexOperation.BuildDefaultName(columns)) 
          { 
           bool unique = info.Entries[0].Index.IsUnique; 
           var name = string.Format("{0}_{1}_{2}", unique ? "UX" : "IX", entitySet.Table, string.Join("_", columns)); 
           if (name.Length > 128) name = name.Substring(0, 128); 
           if (info.Name == name) continue; 
           foreach (var entry in info.Entries) 
           { 
            var index = new IndexAttribute(name); 
            if (entry.Index.Order >= 0) 
             index.Order = entry.Index.Order; 
            if (entry.Index.IsUniqueConfigured) 
             index.IsUnique = entry.Index.IsUnique; 
            if (entry.Index.IsClusteredConfigured) 
             index.IsClustered = entry.Index.IsClustered; 
            entry.Index = index; 
            entry.Modified = true; 
           } 
          } 
         } 
         // Apply the changes 
         foreach (var g in indexInfo.SelectMany(e => e.Entries).GroupBy(e => e.Annotation)) 
         { 
          if (g.Any(e => e.Modified)) 
           g.Key.Value = new IndexAnnotation(g.Select(e => e.Index)); 
         } 
        } 
    
        class IndexInfo 
        { 
         public string Name; 
         public List<IndexEntry> Entries = new List<IndexEntry>(); 
        } 
    
        class IndexEntry 
        { 
         public EdmProperty Column; 
         public MetadataProperty Annotation; 
         public IndexAttribute Index; 
         public bool Modified; 
        } 
    } 
    

    必要なのは、あなたのOnModelCreatingDbModelBuilder.Conventionsにそれを追加することです:

    modelBuilder.Conventions.Add<IndexNameConvention>(); 
    
    +1

    Boy!これは多くの忍耐を取らなければなりませんでした! –

    +0

    @GertArnold実際には、EFソースを調べてコードを書くよりも、答えを構成するのがずっと難しくなりました:) –

    +0

    @IvanStoev私もソースを取得しようとしましたが、かなり難しかったです... –

    関連する問題