**現在解決済み。編集2および編集3を参照してください**
私はNHibernate初心者です-1週間前ですが、それを使って作業することで、新しいプロジェクトの時間を節約できます。NhibernateにParent-ChildCollectionをSQLサーバーデータベースに保存させようと頭を悩ませてきました。
私のクラスマップ:
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Table("orders");
Not.LazyLoad();
Id(x => x.Id,"id");
Map(x => x.Status, "status").CustomType(typeof(OrderStatus)).Not.Nullable();
Map(x => x.PurchaseOrder, "purchaseorder").Not.Nullable();
Map(x => x.SalesOrder, "salesorder").Not.Nullable();
Map(x => x.SupplierLocationId, "shipfrom").Not.Nullable();
Map(x => x.CustomerLocationId, "shipto").Not.Nullable();
Map(x => x.TypeOfShipment, "shipmenttype").CustomType(typeof (ShipmentType)).Not.Nullable();
HasMany(x => x.OrderLineItems).Table("orderitems").KeyColumns.Add("orderid").Cascade.All();
}
}
public class OrderLineMap : ClassMap<OrderLine>
{
public OrderLineMap()
{
Table("orderitems");
Not.LazyLoad();
Id(x => x.Id,"id");
Map(x => x.Order.Id, "orderid").Not.Insert().Not.Update();
Map(x => x.PartNumber, "partnumber");
Map(x => x.LineNumber, "linenumber");
Map(x => x.ReleaseNumber, "releasenumber");
Map(x => x.Quantity, "quantity");
Map(x => x.AttachedQuantity, "attached");
Map(x => x.ActivatedQuantity, "activated");
Map(x => x.ReshippedQuantity, "reshipped");
Map(x => x.ReturnRequestQuantity, "requestreturn");
Map(x => x.ReturnedToSupplierQuantity, "returnedtosupplier");
Map(x => x.ReturnedFromResellerQuantity, "returnedfromreseller");
Map(x => x.SplitQuantity, "split");
Map(x => x.CombineQuantity, "combine");
Map(x => x.Status, "status").CustomType(typeof(OrderLineStatus));
Map(x => x.ReferenceOrderId, "reforderid");
Map(x => x.ReferenceOrderLineId, "reforderlineid");
References(oi => oi.Order, "id");
}
}
HasMany操作を実行しようとしています。今、私は(SOやブログの他の多くの投稿から)OrderItemsにOrdersクラスの参照がないと不可能であると信じさせられました
NunitとNHProfilerを介してテストを行っており、注文の挿入ステートメントがプロファイリングされています...
OrderTesting.CreateNewOrder : FailedNHibernate.StaleStateException : Unexpected row count: 0; expected: 1
at NHibernate.AdoNet.Expectations.BasicExpectation.VerifyOutcomeNonBatched(Int32 rowCount, IDbCommand statement)
at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation)
at NHibernate.Persister.Collection.AbstractCollectionPersister.PerformInsert(Object ownerId, IPersistentCollection collection, IExpectation expectation, Object entry, Int32 index, Boolean useBatch, Boolean callable, ISessionImplementor session)
at NHibernate.Persister.Collection.AbstractCollectionPersister.Recreate(IPersistentCollection collection, Object id, ISessionImplementor session)
at NHibernate.Action.CollectionRecreateAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at Repository.OrderRepository.Save(Order entity) in OrderRepository.cs: line 30
それを解決する方法についての助けはありがたいです。
ありがとうございました、
3月
編集:ジョセフが尋ねたように変更を加えた後、NHプロファイラーに表示される更新ステートメント:
UPDATE orderitems
SET partnumber = 670712 /* @p0 */,
linenumber = 1 /* @p1 */,
releasenumber = 1 /* @p2 */,
quantity = 2 /* @p3 */,
attached = 0 /* @p4 */,
activated = 0 /* @p5 */,
reshipped = 0 /* @p6 */,
requestreturn = 0 /* @p7 */,
returnedtosupplier = 0 /* @p8 */,
returnedfromreseller = 0 /* @p9 */,
split = 0 /* @p10 */,
combine = 0 /* @p11 */,
status = 0 /* @p12 */,
reforderid = '00000000-0000-0000-0000-000000000000' /* @p13 */,
reforderlineid = '00000000-0000-0000-0000-000000000000' /* @p14 */,
orderid = NULL /* @p15 */
WHERE id = '66f8c7c6-ece6-47c6-93f0-b8e1975a96dc' /* @p16 */
編集2:更新ステートメントの解決
子クラスマップで、ID行を次のように変更します。
Id(x => x.Id, "id").GeneratedBy.Assigned().UnsavedValue(null);
編集3:インサートを改善する
上記のコードに基づいて、NHプロファイラーは、永続化されているオブジェクトインスタンスごとに、最初にselectステートメントを生成し、それに基づいてオブジェクトインスタンスが新しいかダーティかを判断することを示します。それを回避するには、Interceptorを次のように使用します
http://www.kkaok.pe.kr/doc/hibernate/reference/html/example-parentchild.html
Interceptorの実装方法については、記事の一番下に移動してください。永続クラスは、データベースに保存する必要があるエンティティの基本クラスになります。インターセプターは、セッションを起動するために登録する必要があります
インターセプターがイベントに置き換えられたことを読みました。それについて多くを読むことができませんでしたが、Interceptorは私にとって素晴らしい働きをします。