子テーブルとのオプションの1:1 関係を持つ親テーブルがあります (親は子なしで存在できますが、その逆はできません)。親テーブルの自動生成された主キーは、子の主/外部キーとして使用されます。
いくつかの良い参考文献 (この質問とこのサイト)のおかげで、1 対 1 の関係を計画することができました。予想どおり、子の有無にかかわらず親を作成し、一方または両方を更新し、親カスケードを削除して子を削除できます。
ただし、マッピング構造内のマッピングのCascade.AllDeleteOrphan()
オプションを何とか「シミュレート」したいので、関係の子側が削除されると、親オブジェクトが保存されるときに子テーブルの対応する行が削除されます。そのまま、子を手動で削除しようとすると、当然のことながらエラー メッセージが表示されます。HasMany
HasOne
'deleted object would be re-saved by cascade'
HasOne
まだマッピングのみを使用しているときに、これを行う良い方法を見つけた人はいますか? 私がやろうとしていることは、まだ 1 対 1 の関係でしょうか? それとも、1 対多を使用して、データベースの制約とビジネス ロジックに依存して、複数の子を防止する必要がありますか?
簡略化されたコード:
// Parent class
public partial class Parent
{
public int pkParentID { get; set; }
public Child child { get; set; }
public Parent() { }
}
// Child class
public partial class Child
{
public int pkParentID {get; set; }
public Parent parent { get; set; }
public Child() { }
public Child(Parent parent) { this.parent = parent; }
}
// Parent mapping
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Table(@"Parent");
LazyLoad();
Id(x => x.pkParentID)
.Column("pkProjectID")
.Not.Nullable()
.GeneratedBy.Identity();
HasOne<Child>(x => x.Child)
.PropertyRef(r => r.Parent)
.Cascade.All();
}
}
// Child map
public class ChildMap :ClassMap<Child>
{
public ChildMap()
{
Table(@"Child");
LazyLoad();
Id(x => x.pkParentID, "pkParentID")
.GeneratedBy.Foreign("Parent");
HasOne<Parent>(x => x.Parent)
.Constrained()
.ForeignKey()
.Cascade.None();
}
}
// Ideally, the code snippet below would remove the row from the Child table
Parent parent = service.GetById(uniqueID);
if (parent.Child != null)
parent.Child = null;
service.SaveOrUpdate(parent);
// Just in case, here's my repository code
public virtual void SaveOrUpdate(T entity)
{
ISession _session = NHibernateSessionProvider.GetSession();
if (!_session.Transaction.IsActive)
{
using (ITransaction transaction = _session.BeginTransaction())
{
try
{
_session.SaveOrUpdate(entity);
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}
}
編集::次のコードスニペットも試しました。これにより、「削除されたオブジェクトはカスケードによって再保存されます」というエラーメッセージが表示されます。
...
Parent parent = parentService.GetById(uniqueID);
if (parent.Child != null)
{
childService.Remove(parent.Child); // this gives the above error
parent.Child = null;
}