4

私はこれを簡潔に保つように努めますが、うまくいけば、私のトラブルで重要な情報を見逃すことはありません。私が信じるコードはすべての詳細を提供しますが、私はノイズを省略しました(VBなので、ノイズがたくさんあります:))。

「Case」オブジェクトには多くの「Assignments」があります。

Public Class Case
  Property CaseId As Guid 
  Property Assignments As ISet(Of CaseAssignment)
End Class

Public Class CaseAssignment
  Property Case As Case
  Property RoleId As Guid
End Class

私が渡したデータモデルは、CaseAssignmentが複合キーであることを除けば、期待どおりのように見えます。

table Case
   CaseId uniqueid not null primary key
   ...

table CaseAssignment
   CaseId uniqueid not null
   RoleId uniqueid not null
   PK := (CaseId, RoleId)
   FK from CaseId -> Case.CaseId

最後に、流暢なNHibernateマッピング:

Class CaseMapping
  Public Sub New()
    Table("Case")
    KeyColumn("CaseId")
    HasMany(Function(x) x.Assignments).KeyColumn("CaseId").Cascade.AllDeleteOrphan()
End Class

Class CaseAssignmentMapping
  Public Sub New()
    Table("CaseAssignment")
    CompositeId() _
      .KeyReference(Function(x) x.Case, "CaseId") _
      .KeyProperty(Function(x) x.RoleId)
End Class

KeyReferenceは、XMLマッピング用語の「key-many-to-one」と相関関係があります。

ケースに割り当てを追加するとすべて問題ありませんが、参照を削除すると2つの問題のいずれかが発生します。このコードで:

aCase.Assignments.Remove(someAssignment)
caseRepository.Save(aCase)

返されるエラーは、「コレクション行を削除できませんでした。..値NULLを列'CaseId'、テーブル'CaseAssignments'に挿入できません。列はnullを許可しません。UPDATEは失敗します。ステートメントは終了しました。」これは、次のSQLを発行しようとしたことによるものです。

UPDATE CaseAssignments SET CaseId = null
WHERE CaseId = @p0 AND RoleId = @p1 AND CaseId = @p2
@p0=[valid guid #1],
@p1=[valid guid #2],
@p2=[valid guid #1 again] **!?!**

少しめちゃくちゃです。だから私はこのコードを試してみます:

aCase.Assignments.Remove(someAssignment)
someAssignment.Case = Nothing
caseRepository.Save(aCase)

NHibernateが次のことを試みたため、エラーは「予期しない行数:0;期待される:1」です。DELETEFROM CaseAssignments WHERE RoleId = [valid guid] AND CaseId = NULL

私はスレッドとフォーラム、およびNHibernateとHibernateのドキュメントを精査してきましたが、実際にはまだ似たようなものに出くわしていません。うまくいけば、それは単純なものです。これを撮ってくれた人に感謝します!

4

1 に答える 1

9

私は数日前に同じ問題を抱えていました。解決策は、CaseMapping クラスの CaseAssignments のコレクションで "inverse" 属性を "true" に設定することです。このような:

HasMany(Function(x) x.Assignments).KeyColumn("CaseId").Cascade.AllDeleteOrphan().Inverse()

私の知る限り、これが機能するには、AllDeleteOrphan カスケード タイプと Inverse プロパティの両方を true に設定する必要があります。

うまくいくことを願っています!

于 2010-01-13T13:40:18.403 に答える