1

由于 SQL Azure 需要每个表的聚集索引以进行复制(请参见此处http://blogs.msdn.com/b/sqlazure/archive/2010/05/12/10011257.aspx),我已将以下 MsSqlAzureDialect 添加到我的 MsSqlConfiguration 中:

public class MsSqlAzureDialect : MsSql2008Dialect
{
    public override string PrimaryKeyString
    {
        get { return "primary key CLUSTERED"; }
    }
}

但是,这并不能解决我目前在使用多对多表时遇到的问题。我目前的情况是,我有一个具有角色的用户,一个具有用户的角色。所以用户和角色之间存在多对多的关系,以及由 NHibernate 生成的链接表。所以在我的 UserAutomappingOverride 我有这样的东西:

public class UserAutomappingOverride : IAutoMappingOverride<User>
{
    public void Override(AutoMapping<User> mapping)
    {
        mapping.HasManyToMany(x => x.Roles).Cascade.SaveUpdate();
    }
}

这导致 NHibernate 创建一个名为 RoleToUser 的链接表。但是,此表没有 PK,因此没有聚集索引。这是在 SQL Azure 中使用的无效表配置。

我尝试使用来自非流利 NHibernate 的数据库对象,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<nhibernate-mapping>
    <database-object>
        <create>create clustered index ix on RoleToUser(User_id, Role_id)</create>
        <drop>drop index RoleToUser.ix</drop>
    </database-object>
</nhibernate-mapping>

但这是在黑暗中尝试将非流利的 NHibernate 代码组合到流利的配置中。但是它不起作用,因为错误提示“出于安全原因,此 XML 文档中禁止使用 DTD...”

注意:我使用 fluent NHibernate 进行代码优先数据库创建。所以我实际上是在使用我的实体和 AutomappingOverrides 在部署时生成数据库的架构。

任何帮助将非常感激。

4

4 回答 4

1

要使用主键生成映射表,您可以使用 IBag。根据我的研究,Fluent NHibernate 尚不支持此功能,但您可以使用 Fluent NHibernate 将 hbm 文件与您的类映射和/或自动映射一起映射,以获取 Fluent NHibernate 不直接支持的功能。

这是一个将用户映射到角色的快速示例:

程序.cs

class Program
{
    static void Main(string[] args)
    {
        DatabaseContextFactory.CreateSchema();

        var user = new User();
        user.Roles = new List<Role>();
        var role = new Role();
        user.Roles.Add(role);

        ISessionFactory sessionFactory = DatabaseContextFactory.CreateSessionFactory();

        using (ISession session = sessionFactory.OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.SaveOrUpdate(role);
                session.SaveOrUpdate(user);
                transaction.Commit();
            }
        }
    }
}

数据库上下文工厂.cs

public static class DatabaseContextFactory
{
    static ISessionFactory _sessionFactory;
    static Configuration _configuration;

    public static ISessionFactory CreateSessionFactory()
    {
        if (_sessionFactory == null)
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008.ConnectionString(cs => cs.FromConnectionStringWithKey("SurrogateExample")))
                .ExposeConfiguration(c => _configuration = c)
                .Mappings(cfg => cfg.HbmMappings.AddFromAssemblyOf<Program>())
                .BuildSessionFactory();
        }

        return _sessionFactory;
    }

    public static void CreateSchema()
    {
        CreateSessionFactory();
        new SchemaExport(_configuration).Execute(false, true, false);
    }
}

用户.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                                     assembly="SurrogateManyToManyExample"
                   namespace="SurrogateManyToManyExample.Entities">
    <class name="User" table="[User]">
        <id name="Id">
            <generator class="guid.comb" />
        </id>

        <idbag name="Roles" table="UserInRole" lazy="true">
            <collection-id column="Id" type="Guid">
                <generator class="guid.comb" />
            </collection-id>
            <key column="UserId" />
            <many-to-many column="RoleId" class="Role" fetch="join" />
        </idbag>
    </class>
</hibernate-mapping>

角色.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                                     assembly="SurrogateManyToManyExample"
                   namespace="SurrogateManyToManyExample.Entities">
    <class name="Role" table="[Role]">
        <id name="Id">
            <generator class="guid.comb" />
        </id>       
    </class>
</hibernate-mapping>
于 2012-06-12T19:02:16.270 回答
1

所以@Derek Greer 的回答很棒。但是,我不希望有太多混合的休眠和流畅的休眠环境。

所以我最终要做的是,因为这些都是将聚集索引添加到 SQL Azure 的链接表的小技巧,所以我最终要做的是添加一个专门用于添加聚集索引的 hbm 文件。这样,每当在自动映射中流畅地向对象添加多对多关系时,开发人员都可以手动向文件添加一行,如下所示。这实际上非常接近我之前找到的答案,但我只是对非流利的 nhibernate 了解得不够多,无法知道我在加载 hbm 文件时做错了什么。所以,这里是:

ManyToManyClusteredIndexes.hbm.xml

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Bookstore.Data.HbmMappings"
assembly="Bookstore.Data.HbmMappings">
    <database-object>
        <create>create clustered index ix on RoleToUser(User_id, Role_id)</create>
        <drop>drop index RoleToUser.ix</drop>
    </database-object>
    <database-object>
        <create>create clustered index ix on RoleToRoleGroup(RoleGroup_id, Role_id)</create>
        <drop>drop index RoleToRoleGroup.ix</drop>
    </database-object>
</hibernate-mapping>
于 2012-06-13T02:36:13.363 回答
1

我有一个在 Azure 中工作的这样的结构

CREATE TABLE [dbo].[ClientLabel](
    [ClientId] [bigint] NOT NULL,
    [LabelId] [bigint] NOT NULL,
 CONSTRAINT [PK_ClientLabel] PRIMARY KEY CLUSTERED 
(
    [ClientId] ASC,
    [LabelId] ASC
) WITH (..) ON [PRIMARY]
) ON [PRIMARY]
于 2012-06-11T23:20:55.180 回答
0

我正在研究这个主题很长时间,因为我不想改变流利的 nhibernate 和 nhibernate 代码,所以我决定做这个解决方法:

我已经有一个控制台应用程序正在初始化数据库环境(本地或天蓝色),在流畅的 nhibernate 数据库创建结束后,我刚刚删除了 ManyToMany 表,并按照天蓝色的预期重新创建它们:

drop table ProfileLikes
CREATE TABLE ProfileLikes(
    [ProfileID] [bigint] NOT NULL,
    [LikeID] [bigint] NOT NULL,
    PRIMARY KEY CLUSTERED 
(
    [ProfileID],[LikeID]  ASC
)
) 

ALTER TABLE ProfileLikes  WITH CHECK ADD  CONSTRAINT [FK6FB4BC1C85106EB3] FOREIGN KEY([LikeID])
REFERENCES [dbo].[Likes] ([Id])
ALTER TABLE ProfileLikes CHECK CONSTRAINT [FK6FB4BC1C85106EB3]

ALTER TABLE ProfileLikes  WITH CHECK ADD  CONSTRAINT [FK6FB4BC1CA12A6EC5] FOREIGN KEY([ProfileID])
REFERENCES Profiles ([Id])

ALTER TABLE ProfileLikes CHECK CONSTRAINT [FK6FB4BC1CA12A6EC5]

希望能帮助到你。阿米尔

于 2012-06-24T11:40:22.460 回答