0

我正在尝试找出流利的 nhibernate 中以下一对多关系的持久性规范应该是什么......

抱歉,代码墙...我尝试了很多方法,但都没有奏效...

还有谁能告诉我为什么每次(不)运行时都会发出第一个选择?!这应该非常简单,但我现在已经花了几个小时,我正准备放弃 Fluent NHibernate ......可能只写一些 SQL 更容易!!!!!!

public class Order
{
    public virtual int OrderId { get; set; }
    private IList<Item> items = new List<Item>();
    public virtual IEnumerable<Item> Items
    {
        get
        {
            return items;
        }
    }

    public virtual void AddItem(Item item)
    {
        items.Add(item);
        item.Order = this;
    }

    public virtual void RemoveItem(Item item)
    {
        item.Order = null;
        items.Remove(item);
    }
}

public class OrderMap : ClassMap<Order>
{
    public OrderMap()
    {
        Id(x => x.OrderId).GeneratedBy.Assigned();
        HasMany(x => x.Items)
            .Inverse()
            .Cascade.All()
            .Access.CamelCaseField();
    }
}

[TestClass]
public class OrderMapTest : BaseDatabaseTest
{
    [TestMethod]
    public void ShouldMapOrder()
    {
        new PersistenceSpecification<Order>(_session)
            .CheckProperty(x => x.OrderId, 1)
            .CheckList(x => x.Items, new List<Item>() { new Item() { Id = 1, Order = new Order() { OrderId = 1 } } })
            .VerifyTheMappings();

        //Test Name:    ShouldMapOrder
        //Test Outcome: Failed
        //Result Message:   
        //Test method Jobs.Test.DatabaseTests.Entity.Base.OrderMapTest.ShouldMapOrder threw exception: 
        //NHibernate.Exceptions.GenericADOException: could not update: [Jobs.Test.DatabaseTests.Entity.Base.Item#1][SQL: UPDATE "Item" SET Order_id = ? WHERE Id = ?] ---> System.Data.SQLite.SQLiteException: constraint failed
        //foreign key constraint failed
        //Result StandardOutput:    
        //NHibernate: 
        //    SELECT
        //        order_.OrderId 
        //    FROM
        //        "Order" order_ 
        //    WHERE
        //        order_.OrderId=@p0;
        //    @p0 = 1 [Type: Int32 (0)]
        //NHibernate: 
        //    INSERT 
        //    INTO
        //        "Item"
        //        (Order_id, Id) 
        //    VALUES
        //        (@p0, @p1);
        //    @p0 = NULL [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
        //NHibernate: 
        //    UPDATE
        //        "Item" 
        //    SET
        //        Order_id = @p0 
        //    WHERE
        //        Id = @p1;
        //    @p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
    }
}

public class Item
{
    public virtual int Id { get; set; }
    public virtual Order Order { get; set; }
}

public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(x => x.Id).GeneratedBy.Assigned();
        References(x => x.Order);
    }
}

[TestClass]
public class ItemMapTest : BaseDatabaseTest
{
    [TestMethod]
    public void ShouldMapItem()
    {
        var Order = new Order() { OrderId = 1 };
        var Item = new Item() { Id = 1 };
        Order.AddItem(Item);

        new PersistenceSpecification<Item>(_session, new ItemComparer())
            .CheckProperty(x => x.Id, Item.Id)
            .CheckReference(x => x.Order, Order)
            .VerifyTheMappings();

        //Test Name:    ShouldMapItem
        //Test Outcome: Failed
        //Result Message:   
        //Test method Jobs.Test.DatabaseTests.Entity.Base.ItemMapTest.ShouldMapItem threw exception: 
        //NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 1, of entity: Jobs.Test.DatabaseTests.Entity.Base.Item
        //Result StandardOutput:    
        //NHibernate: 
        //    SELECT
        //        item_.Id,
        //        item_.Order_id as Order2_0_ 
        //    FROM
        //        "Item" item_ 
        //    WHERE
        //        item_.Id=@p0;
        //    @p0 = 1 [Type: Int32 (0)]
        //NHibernate: 
        //    INSERT 
        //    INTO
        //        "Order"
        //        (OrderId) 
        //    VALUES
        //        (@p0);
        //    @p0 = 1 [Type: Int32 (0)]
        //NHibernate: 
        //    INSERT 
        //    INTO
        //        "Item"
        //        (Order_id, Id) 
        //    VALUES
        //        (@p0, @p1);
        //    @p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]

    }
}
4

1 回答 1

1

我让 ShouldMapOrder 进行以下更改:

var order = new Order{OrderId = 1};
new PersistenceSpecification<Order>(Session, new ItemComparer())
    .CheckList(x => x.Items, new List<Item>() { new Item { Id = 1, Order = order } })
    .VerifyTheMappings(order);

这样做可以让您将 Item 中的反向指针设置为现有的 Order。

为了让它工作,我不得不向 ItemMap 添加一个级联:

public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(x => x.Id).GeneratedBy.Assigned();
        References(x => x.Order).Cascade.SaveUpdate();
    }
}

我不得不给 Order.Items 一个二传手:

public virtual IEnumerable<Item> Items
{
    get { return items; }
    set { items = value.ToList(); }
}

这部分基于对PersistenceSpecification 和 inverse的回答。

它正在执行选择以查看订单是否已经存在。它在会话中没有足够的上下文来判断是进行插入还是更新。

于 2013-07-04T15:31:57.520 回答