I am using Fluent-NHibernate (with automapping) to generate my tables but would like to choose a different clustered index than the ID field which is used by default. How ca
As you said yourself, another option is to switch to the guid.comb ID generation strategy where PK uids are based on a part which is a Guid and a part which ensures that the generated IDs are sequential.
Check out more info in a post by Jeffrey Palermo here.
But you mention that do not want to do that for security reasons - why is that?
This is an old post, but I hope could help someone else. This come from my experience on MS SQL Server. I believe different platforms require different solutions, but this should be a good starting point.
NHibernate doesn't set the CLUSTERED index on the primary key. It's the SQL Server default behavior. As there can be only one CLUSTERED per table, we need first to avoid the CLUSTERED creation on the primary key.
The only way I found to accomplish this is to create a custom Dialect, overriding the propery PrimaryKeyString. NHibernate's default comes from Dialect.cs:
public virtual string PrimaryKeyString
{
get { return "primary key"; }
}
For SQL Server
public override string PrimaryKeyString
{
get { return "primary key nonclustered"; }
}
This will force SQL Server to create a NONCLUSTERED primary key. Now you can add your own CLUSTERED index on your favorite column through the tag in the XML mapping file.
<database-object>
<create>
create clustered index IX_CustomClusteredIndexName on TableName (ColumnName ASC)
</create>
<drop>
drop index IX_CustomClusteredIndexName ON TableName
</drop>
</database-object>
Just like @abx78 told, this is an old post, but I would like to share my knowledgde on a solution for this problem as well. I built the solution for idea 3 "Fluent NHibernate exposes mappings":
After the configuration has been build (thus the mappings are parsed), Fluent NHibernate gives us the oppertunity to look into the actual mappings with configuration.ClassMappings
and configuration.CollectionMappings
. The latter is used in the example below to set a composite primary key resulting in a clustered index in Sql Server (as @abx78 points out):
foreach (var collectionMapping in configuration.CollectionMappings) {
// Fetch the columns (in this example: 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
// >> This part could be changed to a UniqueKey or to an Index
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;
// <<
}
Source: Fluent NHibernate: How to create a clustered index on a Many-to-Many Join Table?
I can't answer that specifically, but I'll give you some database info since I'm here.
You'll need to tell NHibernate to create the primary key at a non-clustered index. There can only be only clustered index per table, so you need to create the table as a heap, and then put a clustered index on it.