3

SQLAzureでFluentNHibernateマッピングを使用するには、すべてのテーブルにクラスター化インデックスが必要です。Fluent NHibernateが多対多結合用に作成するデフォルトのヒープテーブルは、主キーを持たないため、明らかにこれを行いません。

関係の片側に、結合テーブルのクラスター化インデックスを作成するように指示できるようにしたいのですが、その方法がわかりません。私のマッピングは次のようになります。

 public class UserMap : ClassMap<User>{
    public UserMap()
    {
        Table("Users");
        Id(x => x.UserId).GeneratedBy.Identity().Column("UserId");
        Map(x => x.UserName).Unique().Not.Nullable().Length(DataConstants.UserNameLength).Column("UserName");
        Map(x => x.Email).Unique().Not.Nullable().Length(DataConstants.EmailAddressLength).Column("Email");
        Map(x => x.Password).Not.Nullable().Length(DataConstants.PasswordHashLength).Column("Password");
        HasMany(x => x.Clicks).Cascade.AllDeleteOrphan();
        HasManyToMany(x => x.Roles).Cascade.SaveUpdate().Table("UsersInRole").ParentKeyColumn("UserId").
            ChildKeyColumn("RoleId");

    }
}

さらに情報が必要な場合はお知らせください。

4

4 に答える 4

5

Fluentが直接サポートしているかどうかはわかりませんが(サポートしていない場合は、xmlを含めるだけです)、補助データベースオブジェクトを使用してサポートできます。

<nhibernate-mapping>
  <database-object>
    <create>create clustered index ix on UsersInRole(UserId, RoleId)</create>
    <drop>drop index UsersInRole.ix</drop>
  </database-object>
</nhibernate-mapping>
于 2011-02-02T02:12:01.547 に答える
2

トピックスターターと同じ問題に苦労しましたが(FluentNHibernateとSqlAzureも組み合わせているため)、与えられた答えは満足のいくものではありませんでした。これは、慣例により動的ではないためです。もちろん、HBMファイルを動的に作成し、後で構成に追加することもできますが、HBMファイルが気に入らないので、もっと良いconfiguration.AddXmlFile("AddClusteredIndexesToManyToManyTables.hbm.xml");方法があるとは思えません。

数時間後、動的(そして読み取り可能!)でhbmxmlファイルを処理しない別のソリューションを見つけました。解決策は次のとおりです。

前提条件1:SQLServerでクラスター化インデックスを作成する各ジャンクションテーブルの複合主キーを作成します。

構成が構築された後(したがって、マッピングが解析されます)、(Fluent)NHibernateは、とを使用して実際のマッピングを調べる機会を提供しconfiguration.ClassMappingsますconfiguration.CollectionMappings。多対多のマッピングに関心があるため、後者が使用されます。

foreach (var collectionMapping in configuration.CollectionMappings
    // Filter on many-to-many
    .Where(x => !x.IsOneToMany)) {
    // Build the columns (in a hacky way...)
    const string columnFormat = "{0}_id";
    var leftColumn = new Column(string.Format(
        columnFormat,
        collectionMapping.Owner.MappedClass.Name));
    var rightColumn = new Column(string.Format(
        columnFormat,
        collectionMapping.GenericArguments[0].Name));
    // Fetch the actual table of the many-to-many collection
    var manyToManyTable = collectionMapping.CollectionTable;
    // Shorten the name just like NHibernate does
    var shortTableName = (manyToManyTable.Name.Length <= 8)
                                ? manyToManyTable.Name
                                : manyToManyTable.Name.Substring(0, 8);
    // Create the primary key and add the columns
    var primaryKey = new PrimaryKey {
        Name = string.Format("PK_{0}", shortTableName),
    };
    primaryKey.AddColumn(leftColumn);
    primaryKey.AddColumn(rightColumn);
    // Set the primary key to the junction table
    manyToManyTable.PrimaryKey = primaryKey;
}

そして、はい、左側と右側の列を取得するロジックその後、列は少しハックですが、それは機能し、私のソリューションを自由に調整および編集できます(^ _-)。問題は、コレクションのマッピングがかなり空であるか、埋められていないことです。

規則のコーディングと作成に頑張ってください!

于 2012-06-12T11:43:29.143 に答える
0

列の任意のセットをクラスター化インデックスにすることができます...クラスター化インデックスを作成するためにPK制約を使用する必要があることを私が知っている必要はありません。

さらに、クライアントがクラスター化されたインデックスを要求する方法がわかりません。それはそれらをデフォルトにするかもしれませんが、それは必要とは異なります。これはSQLServerの「ベストプラクティス」として報告されることがよくありますが、クライアントにとっては、列のセカンダリbツリーインデックスとテーブルのレコードを並べ替えるクラスター化インデックスの間に実際の違いはありません。クライアントは、データの基盤となるストレージをどのように区別できますか?1つはクラスターキー順にデータを保存し、もう1つは保存しません。

流暢なnhibernateの方がパフォーマンスが優れているか、主張して​​いるかもしれませんが、インデックスがなくても「機能」します。

しかし、私もYMMVの専門家ではありません。

于 2011-02-02T00:41:30.297 に答える
-2

素晴らしいソリューションM.Mimpen。

マップインターフェイスが必要な場合は、インターフェイス名を使用してChildKeyColumnを配置します。

例:HasManyToMany(x => x.Acessos)。( "IRole_id");

クラスAcessoはIRoleインターフェースを実装します。子キー名を通知しない場合、作成される列は「Acesso_id」になりますが、キーを作成するときに「IRole_id」が試行されます。

于 2015-03-26T21:38:38.767 に答える