0

私は現在、SQL Server 2000データベースを使用して古いASPアプリケーションに取り組んでおり、.NETとNHibernateを使用して新しいテクノロジに移植しようとしています。

そのDBでは、すべてのテーブルに次のように作成された複合IDがあります。

CREATE TABLE [Languages](
    [languageIncId] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [languageSqlId] [smallint] NOT NULL,
    ...
    [createdByIncId] [int] NOT NULL,
    [createdBySqlId] [smallint] NOT NULL,
    ...
    [lastModifiedByIncId] [int] NULL,
    [lastModifiedBySqlId] [smallint] NULL,
    [rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
        ...
 CONSTRAINT [PK_Languages] PRIMARY KEY CLUSTERED 
(
    [languageIncId] ASC,
    [languageSqlId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO

つまり、各テーブルの主キーは次のもので構成されます。

  • アイテムが作成されたSQLServerインスタンスのIDであるXXXSqlId
  • IDENTITY新しい行が挿入されたときにインクリメントされるフィールドであるXXXIncId

重要なのSqlIdは、レプリケーションが発生すると、レコードがデータベースから別のデータベースに移動され、複製XXXIncIdが発生する可能性があるということです。残念ながら、多くのアプリケーションがデータベーススキーマに依存しているため、データベーススキーマを変更することはできません(これは確かに苦痛です)。

これは、テーブル間に関係が存在する場合は常に、のように両方のフィールドを指定する必要があることも意味しcreatedByIncId , createdBySqlIdます。

この構造をNHibernate(流暢かどうか)でマッピングするための最良の方法を探していますが、ブロックされています。私は次の解決策を検討しました:

  • SqlIdおよびIncId(最も自然なソリューション)でComposite-IDを使用しますが、IncIdはデータベースによって生成され、CompositeIDは「生成された」属性をサポートしないため、機能しません。
  • これらのフィールドを完全に無視し、「rowguid」を実際のIDと見なします。これは、「複合ID」をリンクとして使用する必要があるエンティティ間の関係を試さない限り、うまく機能します...
  • カスタムコンポジットユーザータイプICompositeUserType)を使用する:ただし、これをエンティティのIDとして使用することはできません。

私の質問は質問1615647にかなり似ていますが、答えは私にとって満足のいくものではありません。

フォローする別のリードのアイデアはありますか?

4

1 に答える 1

0

2つのリードを試しました:

  • カスタムは、フィールドを<sql-insert>含まないSQLクエリ( )を挿入し、挿入のたびに追加のSQLクエリを実行して、プロパティを手動で入力します。IDENTITYこれは単純なユースケース(単純なSELECT / INSERT)では正常に機能しましたが、他のエンティティおよび他のエンティティのコレクションを参照するとすぐには機能しませんでした...

  • 主キーとして別のフィールドを使用します。各テーブルにはrowguid列もあります。これをNHibernateの実際の主キーとして使用します。これは、カスケードされた挿入/更新のテストケースで正常に機能しました。複合IDは、挿入時に生成されたものとしてマークされ、更新中に含まれない通常のコンポーネントです。次のようになります。

    Component<CustomCompositeIdType>(e => e.Id,
        p =>
        {
            p.Map(i => i.SqlId, "languageSqlId")
                .Insert()
                .Not.Update()
                .Not.Nullable();
            p.Map(i => i.IncId, "languageIncId")
                .Not.Update()
                .Not.Nullable()
                .Generated.Insert();
        });
    

次に、エンティティ間の参照について、関係を確立するために使用される2つの列を指定します。

多対1:

    References<LanguageEntity>(e => e.Language)
        .Columns("languageSqlId",
                 "languageIncId")
        .PropertyRef(l => l.Id)
        .Fetch.Join()
        .Cascade.None();

1対多:

    HasMany<InterfaceTranslationEntity>(e => e.Translations)
        .KeyColumns.Add("InterfaceSqlId",
                        "InterfaceIncId")
        .PropertyRef("Id") //name of the property in InterfaceTranslationEntity
        .Inverse();
于 2010-12-15T08:30:01.120 に答える