一对多持久性规范不起作用

时间:2013-06-29 18:31:13

标签: .net nhibernate fluent

我正在试图弄清楚持久性规范对于以下一对多关系的流利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)]

    }
}

1 个答案:

答案 0 :(得分: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中的backpointer设置为现有的Order。

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

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

我必须给Order.Items一个setter:

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

部分基于PersistenceSpecification and inverse的答案。

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