1対多関係のあるテーブルでISession.Deleteを実行しようとするとNHibernateでエラーが発生します。Fluent NHibernate MappingがAllDeleteOrphanに設定されていますが、まだDB内の外部キーをnullにしようとしています
NHibernateは、子テーブルの行を単に削除するのではなく、子テーブルの親テーブルへの外部キーをnullに設定しようとしています。ここで
は自分のドメインです:
public class Parent
{
public Parent()
{
_children = new List<Child>();
}
public int Id { get; set; }
public string SimpleString { get; set; }
public DateTime? SimpleDateTime { get; set; }
private IList<Child> _children;
public IEnumerable<Child> Children
{
get { return _children; }
}
public void AddChild(Child child)
{
child.Parent = this;
_children.Add(child);
}
}
public class Child
{
public int Id { get; set; }
public string SimpleString { get; set; }
public DateTime? SimpleDateTime { get; set; }
[JsonIgnore]
public Parent Parent { get; set; }
}
私がセットアップしている流暢NHibernateのマッピングを次のように
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Not.LazyLoad();
Id(x => x.Id);
Map(x => x.SimpleString);
Map(x => x.SimpleDateTime);
HasMany(x => x.Children)
.Not.LazyLoad()
.KeyColumn("ParentId").Cascade.AllDeleteOrphan()
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore);
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Not.LazyLoad();
Id(x => x.Id);
Map(x => x.SimpleString);
Map(x => x.SimpleDateTime);
References(x => x.Parent).Not.Nullable().Column("ParentId").Cascade.All().Fetch.Join();
}
}
私はCascade.AllDeleteOrphan()
にNHibernateのを指示しましたが、まだParentIdはを設定しようとしていますforiegnキーがnullに設定されているのは、私が設定したテストです:
public void Delete_GivenTableWithChildren_WillBeDeletedFromDB()
{
int id;
using (var createSession = MsSqlSessionProvider.SessionFactory.OpenSession())
{
var parent = new Parent();
parent.AddChild(new Child { SimpleString = "new child from UI" });
using (var trx = createSession.BeginTransaction())
{
createSession.Save(parent);
trx.Commit();
id = parent.Id;
}
}
using (var firstGetSession = MsSqlSessionProvider.SessionFactory.OpenSession())
{
var result = firstGetSession.Get<Parent>(id);
Assert.IsNotNull(result);
}
using (var deleteSession = MsSqlSessionProvider.SessionFactory.OpenSession())
{
using (var trx = deleteSession.BeginTransaction())
{
deleteSession.Delete("from " + typeof(Parent).Name + " o where o.Id = :Id", id, NHibernateUtil.Int32);
trx.Commit();
}
}
using (var session = MsSqlSessionProvider.SessionFactory.OpenSession())
{
var result = session.Get<Parent>(id);
Assert.IsNull(result);
}
}
exec sp_executesql N'UPDATE [Child] SET ParentId = null WHERE ParentId = @p0',N'@p0 int',@p0=5
:以下のSQLを試みた後のn deleteSession.Delete
ライン
NHibernate.Exceptions.GenericADOException : could not delete collection: [SaveUpdateOrCopyTesting.Parent.Children#5][SQL: UPDATE [Child] SET ParentId = null WHERE ParentId = @p0]
----> System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'ParentId', table 'SaveUpdateCopyTestingDB.dbo.Child'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
誰もが、私は私のマッピングで間違って何をやったか知っている、またはしようとするからNHibernateのを停止する方法を知っています外部キーのIDをnullにしますか?
おかげ
デイブ
伝説..ありがとうございました.. Inverseは、Parentレコードに挿入する前にChildレコードに挿入しようとすると、Savesが失敗することを意味すると考えました。ちょうど完全に実行されたクルードのテストとすべてのカスケードは、扱います..ありがとう:) – CraftyFella
喜んで助けてください。それは良い説明に役立つ場合は、逆の使用上のまともなSOスレッドがあります:http://stackoverflow.com/questions/1061179/when-to-use-inverse-false-on-nhibernate-hibernate-onetomany-relationships – nkirkes
それは動作します元気? –