Свободное владение NHibernate: Как создать кластерный индекс для таблицы соединений «многие ко многим»? - PullRequest
3 голосов
/ 02 февраля 2011

Чтобы использовать сопоставления Fluent NHibernate в SQL Azure, мне нужно иметь кластеризованный индекс для каждой таблицы. Таблицы кучи по умолчанию, которые 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 ]

5 голосов
/ 02 февраля 2011

Я не знаю, поддерживает ли 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>
2 голосов
/ 12 июня 2012

Я боролся с той же проблемой, что и автор темы (так как я комбинирую также Fluent NHibernate и Sql Azure), но данный ответ не удовлетворил.Это потому, что он не является динамическим по соглашению.Конечно, файл HBM может быть динамически создан и впоследствии добавлен в конфигурацию с помощью configuration.AddXmlFile("AddClusteredIndexesToManyToManyTables.hbm.xml");, но мне просто не нравятся файлы HBM, и я не могу представить, что существует способ лучше .

Через несколько часов я нашел другое решение, которое является динамическим (и читаемым!) И не работает с файлами hbm xml.Решение состоит в следующем:

Предположение № 1: я создам составной первичный ключ для каждой соединительной таблицы, который приводит к кластеризованному индексу в SQL Server.

Послеконфигурация была собрана (таким образом, сопоставления проанализированы), (Свободно) 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;
}

И да, логика для получения левого и правого столбцов. После этого столбцы немного взломаны, но это работает иВы можете настроить и отредактировать мое решение (^ _-).Проблема в том, что отображение коллекции довольно пусто / не заполнено.

Удачи в кодировании и создании соглашений!

0 голосов
/ 27 марта 2015

Отличное решение М.Мимпен.

Когда нужны интерфейсы карты, поместите ChildKeyColumn с именем интерфейса.

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

Класс Acesso реализует интерфейс IRole. Если вы не сообщите имя дочернего ключа, будет создан столбец «Acesso_id», но при создании ключа будет использоваться «IRole_id».

0 голосов
/ 02 февраля 2011

Любой набор столбцов может быть кластеризованным индексом ... я не знаю, какое требование заставляет вас использовать ограничение PK для создания кластеризованного индекса.

БолееЯ не понимаю, как клиент может запросить кластерный индекс. может сделать их по умолчанию , но это не так, как требуется.Об этом часто говорят как о «наилучшей практике» для SQL Server, но для клиента нет реального различия между вторичным индексом b-дерева в столбце и кластерным индексом, который упорядочивает записи таблицы.Как клиент сможет различить базовое хранилище данных?Один хранит данные, упорядоченные по ключу кластера, другой нет.

Возможно, fluent-nhibernate работает лучше или заявляет о себе - но он будет "работать" без каких-либо индексов.

Но я не эксперт ни в одном, поэтому YMMV.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...