Nhibernate 多对多映射 中间表的主键问题1,我原来的主键采用int自增长方式,中间表主键也采用自增int,运行没有问题。
2,但是因为主键为自增型,对于多数据库的同步有问题,所以改为采用36位的无重复数。
   所有主键都改为36位的无重复数后, 测试报错。 大概意思是 nhibernate生成插入中间表SQL时,并没有生成ID,(从映射的意思来看,nhibernate也的确不知道 中间表主键的生成方式,所以也不会生成中间表ID;自增类型,不需要生成中间表ID,所以没有这个问题) 3,我把中间表的ID去掉后,数据就能保存成功了。但是又会在数据表中产生重复的记录。若把中间表两外键组合为主键时,插入相同数据时,会报关联约束错误的。
以上情况,导致多对多映射,采用32位无重复数ID时,会遇到上述问。请问 前辈们遇到此类情况是怎样处理的?小弟先谢过了!

解决方案 »

  1.   

    下面是数据表和测试方法:数据库表:功能表
    create table A_FunctionMenu (
       ID                   char(36)             not null,
       ParentID             char(36)             null,
       ApplicationID        char(36)             null,
       Level                int                  not null,
       SearchCode           varchar(64)          not null,
       FunctionName         varchar(64)          not null,
       IsMenu               bit                  not null,
       MenuURL              varchar(256)         null,
       Type                 char(2)              not null,
       CreateType           char(2)              not null,
       Sort                 int                  not null,
       AddTime              datetime             null,
       UpdateTime           datetime             null,
       IsShow               bit                  not null,
       constraint PK_A_FUNCTIONMENU primary key (ID)
    )角色表
    create table A_Role (
       ID                   char(36)             not null,
       RoleName              varchar(128)        not null,
       Sort                 int                  not null,
       Re               varchar(512)         null,
       IsShow               bit                  not null,
       constraint PK_A_ROLE primary key (ID)
    )
    go角色和功能的中间表
    create table A_RoleFunctionMenu (
       ID                   char(36)             not null,
       RoleID               char(36)             not null,
       FunctionMenuID       char(36)             not null,
       constraint PK_A_ROLEFUNCTIONMENU primary key (ID)
    )
    映射文件
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class name="Sight.Model.Admin.RoleEntity, Sight.Model.Admin" table="A_Role" >
        <id name="ID" access="property">
          <column name="ID" sql-type="char(36)" not-null="true"/>
          <generator class="uuid.hex">
            <param name="format">D</param>
            <param name="seperator">-</param>
          </generator>
        </id>
        <property name="RoleName" column="RoleName" type="String" length="128" />
        <property name="Re" column="Re" type="String" length="512" />
        <property name="Sort" column="Sort" type="Int32" length="4" />
        <property name="IsShow" column="IsShow" type="Boolean"/>    <bag name="FunctionMenus" table="A_RoleFunctionMenu" >
          <key column= "RoleID" />
          <many-to-many class="Sight.Model.Admin.FunctionMenuEntity,Sight.Model.Admin" column="FunctionMenuID" />
        </bag>  </class></hibernate-mapping><?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class name="Sight.Model.Admin.FunctionMenuEntity, Sight.Model.Admin" table="A_FunctionMenu" >
        <id name="ID" access="property">
          <column name="ID" sql-type="char(36)" not-null="true"/>
          <generator class="uuid.hex">
            <param name="format">D</param>
            <param name="seperator">-</param>
          </generator>
        </id>
        
        <!--property name="ParentID" column="ParentID" type="Int32" length="4" /-->
        <property name="Level" column="Level" type="Int32" length="4" />
        <property name="SearchCode" column="SearchCode" type="String" length="64" />
        <property name="FunctionName" column="FunctionName" type="String" length="64" />
        <property name="IsMenu" column="IsMenu" type="Boolean" />
        <property name="MenuURL" column="MenuURL" type="String" length="256" />
        <property name="Type" column="Type" type="String" length="2" />
        <property name="CreateType" column="CreateType" type="String" length="2" />
        <property name="Sort" column="Sort" type="Int32" length="4" />
        <property name="AddTime" column="AddTime" type="DateTime"/>
        <property name="UpdateTime" column="UpdateTime" type="DateTime"/>
        <property name="IsShow" column="IsShow" type="Boolean"/>    <many-to-one name="ParentFunctionMenu" column="ParentID" />    <bag name="ChildFunctionMenus" order-by="Sort desc" cascade="all" lazy="true">
          <key column="ParentID" />
          <one-to-many class="Sight.Model.Admin.FunctionMenuEntity, Sight.Model.Admin" />
        </bag>    <bag name="HasRoles" table="A_RoleFunctionMenu" lazy="true">
          <key column="FunctionMenuID" />
          <many-to-many class="Sight.Model.Admin.RoleEntity,Sight.Model.Admin" column="RoleID" />
        </bag>  </class></hibernate-mapping>运行测试方法:        public void AddFunctionAddRoleTest()
            {
                FunctionMenuBLL functionMenuBLL = new FunctionMenuBLL();
                FunctionMenuEntity functionMenuEntity = new FunctionMenuEntity();
                functionMenuEntity.FunctionName = "权限管理";
                functionMenuBLL.Add(functionMenuEntity);            RoleBLL roleBLL = new RoleBLL();
                RoleEntity role = new RoleEntity();
                role.RoleName = "校长";
                role.IsShow = true;            role.FunctionMenus.Add(functionMenuEntity);            roleBLL.Add(role);  
            }
      

  2.   

    所报错误:------ Test started: Assembly: Sight.Test.Admin.dll ------NHibernate: INSERT INTO A_FunctionMenu (Level, SearchCode, FunctionName, IsMenu, MenuURL, Type, CreateType, Sort, AddTime, UpdateTime, IsShow, ParentID, ID) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12); @p0 = '0', @p1 = '', @p2 = '权限管理', @p3 = 'False', @p4 = '', @p5 = '01', @p6 = '01', @p7 = '0', @p8 = '1900-1-1 0:00:00', @p9 = '1900-1-1 0:00:00', @p10 = 'True', @p11 = '', @p12 = 'c4400f86-bd15-4aed-9660-a6399d4ea33d'
    NHibernate: INSERT INTO A_Role (RoleName, Re, Sort, IsShow, ID) VALUES (@p0, @p1, @p2, @p3, @p4); @p0 = '校长', @p1 = '', @p2 = '0', @p3 = 'True', @p4 = '6612ad26-306f-4259-8490-96e83bddfa81'
    NHibernate: INSERT INTO A_RoleFunctionMenu (RoleID, FunctionMenuID) VALUES (@p0, @p1); @p0 = '6612ad26-306f-4259-8490-96e83bddfa81', @p1 = 'c4400f86-bd15-4aed-9660-a6399d4ea33d'
    TestCase 'M:Sight.Test.Admin.RoleTest.AddFunctionAddRoleTest'
    failed: could not insert collection: [Sight.Model.Admin.RoleEntity.FunctionMenus#6612ad26-306f-4259-8490-96e83bddfa81]
    NHibernate.ADOException: could not insert collection: [Sight.Model.Admin.RoleEntity.FunctionMenus#6612ad26-306f-4259-8490-96e83bddfa81] ---> System.Data.SqlClient.SqlException: 无法将 NULL 值插入列 'ID',表 'Sight.dbo.A_RoleFunctionMenu';该列不允许空值。INSERT 失败。
    语句已终止。
       在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
       在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
       在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
       在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
       在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
       在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
       在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
       在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
       在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
       在 NHibernate.Impl.NonBatchingBatcher.AddToBatch(IExpectation expectation)
       在 NHibernate.Persister.Collection.AbstractCollectionPersister.Recreate(IPersistentCollection collection, Object id, ISessionImplementor session)
       --- 内部异常堆栈跟踪的结尾 ---
       在 Sight.Tool.DataAccess.DAL.SessionManager.Add[T](T entity) 位置 D:\project\SightProject\Sight\Tool\DataAccess\DAL\SessionManager.cs:行号 165
       在 Sight.Tool.BusinessService.BaseBLL`2.Add(T entity) 位置 D:\project\SightProject\Sight\Tool\BusinessService\BaseBLL.cs:行号 32
       在 Sight.Test.Admin.RoleTest.AddFunctionAddRoleTest() 位置 D:\project\SightProject\Sight\Test\Admin\RoleTest.cs:行号 690 passed, 1 failed, 0 skipped, took 6.08 seconds.