为了在SQL Azure上使用我的Fluent NHibernate映射,我需要在每个表上都有一个聚簇索引。 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");
}
}
如果您需要更多信息,请与我们联系!
答案 0 :(得分:5)
我不知道Fluent是否直接支持它(如果没有,只包括xml),但你可以用Auxiliary Database Objects
来支持它<nhibernate-mapping>
<database-object>
<create>create clustered index ix on UsersInRole(UserId, RoleId)</create>
<drop>drop index UsersInRole.ix</drop>
</database-object>
</nhibernate-mapping>
答案 1 :(得分:2)
我遇到了与主题启动器相同的问题(因为我正在将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;
}
是的,获取左右列的逻辑之后,列有点hacky但它可以工作,你可以自由调整和编辑我的解决方案(^ _-)。问题是集合映射相当空/未填充。
祝你好运编码和创建约定!
答案 2 :(得分:0)
任何一组列都可以是聚簇索引...我不需要知道你为了构建聚簇索引而使用PK约束的强制措施。
更多我不明白客户端如何处理聚簇索引。它可能是make them as a default,但这与要求不同。这通常被报告为SQL Server的“最佳实践”,但对于客户端,列上的辅助b树索引与对表记录进行排序的聚簇索引之间没有真正的区别。客户如何区分数据的底层存储?一个存储由群集键排序的数据,另一个不存储。
也许fluent-nhibernate表现得更好,或声称 - 但它会在没有任何索引的情况下“正常工作”。
但我不是YMMV的专家。
答案 3 :(得分:-2)
伟大的解决方案M.Mimpen。
当需要map接口时,请将ChildKeyColumn与接口名称放在一起。
例: HasManyToMany(x =&gt; x.Acessos)。(“IRole_id”);
Acesso类实现了IRole接口。如果您没有通知子密钥名称,则创建的列将为“Acesso_id”,但创建密钥时将尝试“IRole_id”。