Fluent Nhibernate:意外行数:0;预计:1

发布于 2024-09-29 18:58:43 字数 5162 浏览 7 评论 0原文

** 目前已解决。请参阅编辑 2 和编辑 3 **

我是 NHibernate 新手 - 一周了,但我认为使用它会节省我在新项目上的时间,而不是其他。我一直在绞尽脑汁试图让 Nhibernate 将父子集合保存到 SQL 服务器数据库。

alt text

我的类映射:

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");
    }
}

我正在尝试执行Has Many 操作。现在我相信(从 SO 和博客中的许多其他帖子)除非我在 OrderItems

我正在通过 Nunit 和 NH Profiler 进行测试,并且正在分析订单的插入语句...

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

任何有关如何解决该问题的帮助将不胜感激。

谢谢,

Mar

编辑:按照 Joseph 的要求进行更改后,现在可以在 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 Profiler 将显示,对于每个被持久化的对象实例,它将首先生成一个 select 语句,根据该语句,它将确定该对象实例是新的还是脏的。为了避免这种情况,请使用 Interceptor 作为

http://www. kkaok.pe.kr/doc/hibernate/reference/html/example-parentchild.html

导航到文章的最底部,您将在其中找到有关如何实现拦截器的信息。 持久类将是需要保存到数据库的实体的基类。拦截器需要注册来触发会话

我读到拦截器已被事件取代。无法阅读太多内容,但 Interceptor 对我来说非常有用。

** Solved as of now. Please see Edit 2 and Edit 3 **

I am NHibernate Newbie- a week old but I though working with it will save me time on new project and not otherwise. I have been banging my head trying to get Nhibernate to save Parent - Child Collection to SQL server database.

alt text

My Class Map :

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");
    }
}

I am trying to do a Has Many operation. Now I was made to believe (from lot of other posts in SO and Blogs) that it is not possible unless I have a Orders class reference in OrderItems

alt text

I am doing testing through Nunit and NH Profiler and insert statement for orders is getting profiled...

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

Any help will be appreciated on how to solve it.

Thank you,

Mar

Edit: Update statement now seen in NH profiler after making changes as Joseph asked:

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 */

Edit 2: Resolution for Update Statements

In the Child Class Map, change the ID line to:

Id(x => x.Id, "id").GeneratedBy.Assigned().UnsavedValue(null);

Edit 3: Improve inserts

Based on the above code, NH profiler will show that for each object instance being persisted it will first generate a select statement based on which, it will determine if the object instance is new or dirty. To avoid it use Interceptor as

http://www.kkaok.pe.kr/doc/hibernate/reference/html/example-parentchild.html

Navigate to the very bottom of the article where you will find about how to implement Interceptor.
Persistent class will be your base class for your Entities that needs to be saved to database. Interceptor will need to be registered firing the session

I have read that Interceptors have been replaced by events. Could not read a lot on it but Interceptor works great for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝眼泪 2024-10-06 18:58:43

你不应该需要这条线

Map(x => x.Order.Id, "orderid").Not.Insert().Not.Update();

,我认为这可能会让你感到困惑。

另外,当您引用订单时,您需要为其提供外键字段的名称,但您现在似乎没有该名称。

所以你应该有这个

References(oi => oi.Order, "orderid");

You shouldn't need this line

Map(x => x.Order.Id, "orderid").Not.Insert().Not.Update();

I think that might be messing you up.

Also, when you reference your Order, you need to give it the name of the foreign key field, which it looks like you don't have right now.

so you should have this

References(oi => oi.Order, "orderid");
为你鎻心 2024-10-06 18:58:43

你的 OrderLineMap 类不应该有这个:

References(oi => oi.Order, "orderid")

而不是这个:
参考文献(oi => oi.Order, "id")

Shouldn't your OrderLineMap class have this:

References(oi => oi.Order, "orderid")

instead of this:
References(oi => oi.Order, "id")
?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文