Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the column order in a multi-column index using fluent-nhibernate?

How to change the column order in a multi-column index?
I.e:

mapping.References(x => x.SomeReference).SetAttribute("index", "IX_index");
mapping.Map(x => x.SomeField).SetAttribute("index", "IX_index");

Produces the following Schema:

create index IX_index on ApplicantProgramDatas (SomeField, SomeReferenceId)

But I want to get:

create index IX_index on ApplicantProgramDatas (SomeReferenceId, SomeField)
like image 503
3 revs Avatar asked Dec 09 '09 18:12

3 revs


People also ask

Why is column order so important when creating a multicolumn index?

When creating a multicolumn index, the column order is very important. This is due to the structure that multicolumn indexes possess. Multicolumn indexes are structured to have a hierarchical structure. Take for example this table: A traditional index on this table would look like this:

How do I change the Order of columns in a Dataframe?

To change the column order: include the columns argument in the method. Note this method doesn’t have an inplace argument, so we can’t modify the dataframe inplace.

How to use SET_Index with multiple columns in pandas Dataframe?

MultiIndex ( [ ('company A', 'rank'), ('company A', 'points'), ('company B', 'rank'), ('company B', 'points')], ) Now in order to use the method set_index with columns we need to provide all levels from the hierarchical index. To use set_index with multiple columns in Pandas DataFrame we can apply next syntax:

Can the multicolumn index be used for queries just on make/model?

However, the multicolumn index cannot be used for queries just on the make or model of the car because the pointers are inaccessible. Multicolumn indexes work similarly to traditional indexes.


2 Answers

You can define an index in NHibernate using <database-object> or IAuxiliaryDatabaseObject.

In a hbm.xml file:

<hibernate-mapping xmlns="urn:nhiernate-mapping-2.2">
  <database-object>
     <create>VALID SQL</create>
     <drop>VALID SQL</create>
  </database-object>
</hibernate-mapping>

N.B. <database-object> can go before or after a class mapping in the same hbm.xml file allowing you to keep your index definitions, triggers, etc. with the object to which they apply.

The other option is NHibernate.Mapping.IAuxiliaryDatabaseObject:

namespace NHibernate.Mapping {
    public interface IAuxiliaryDatabaseObject : IRelationalModel {
        void AddDialectScope(string dialectName);
        bool AppliesToDialect(Dialect dialect);
        void SetParameterValues(IDictionary<string, string> parameters);
    }
    public interface IRelationalModel {
        string SqlCreateString(Dialect dialect, IMapping p, string defaultCatalog, string defaultSchema);
        string SqlDropString(Dialect dialect, string defaultCatalog, string defaultSchema);
    }
}

Given that you're using Fluent NHibernate, IAuxiliaryDatabaseObject will probably work better for you. Just expose your configuration when building it and then call:

var sqlCreate = "CREATION SCRIPT";
var sqlDrop = "DROP SCRIPT";    
cfg.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(sqlCreate, sqlDrop));

N.B. NHibernate.Mapping.SimpleAuxiliaryDatabaseObject is part of NHibernate. You don't have to write it yourself if all you need to do is supply create/drop scripts for a database object.

I took a quick look in the Fluent NHibernate codebase and didn't see any direct support for IAuxiliaryDatabaseObject. So it is a matter of exposing your configuration object and supplying all your IAuxiliaryDatabaseObjects yourself. It wouldn't be too difficult to write some code that scan through your mapping assembly looking for types that implement IAuxiliaryDatabaseObject and then foreach'ing over them to pass to cfg.AddAuxiliaryDatabaseObject(obj).

You can find more information about auxiliary database objects in the NHibernate docs:

http://nhibernate.info/doc/nh/en/index.html#mapping-database-object

like image 97
James Kovacs Avatar answered Nov 15 '22 08:11

James Kovacs


I guess it is impossible. 'FluentNHibernate.MappingModel.MappedMembers.AcceptVisitor()' iterates properties before references:

        foreach (var collection in Collections)
            visitor.Visit(collection);

        foreach (var property in Properties)
            visitor.Visit(property);

        foreach (var reference in References)
            visitor.Visit(reference);

As a result, you will always have properties before references in multi-column index.

BTW none of the ORMs will give you ability to set non-trivial index options like clustered, filtered, etc.

like image 37
Ben Avatar answered Nov 15 '22 08:11

Ben