Breaking changes with NHibernate 4 upgrade

百般思念 提交于 2019-11-30 23:02:15

FYI, I found a new error that is thrown. We use Mapping By Code, and we used to have an entity that had multiple Bag mappings with the Fetch type set to Join with NHibernate v 3.3.x. This is no longer allowed in version 4.0.x.

We received an error message of Cannot simultaneously fetch multiple bags., which makes sense with what is necessary behind the scenes but it should technically be considered a breaking change. NHibernate was not nice enough to tell us which mapping was causing the issue.

We were experiencing the same issue with a rather large QueryOver - Cannot simultaneously fetch multiple bags, with Nhibernate 4 and FluentNhibernate mappings.

The solution was to, on our FluentMaps, to set AsSet() (according to our backing fields) which in the end solved the issue.

As per request in the comment, here is a small sample of our mappings before and after the exception:

This is a very simplified showcase of our classes which caused the Cannot simultaneously fetch multiple bags. The abstract Entity class belongs to the S#Arp lite architecture. Before the changes it looked something like this

public class OrderHeader : Entity
{
    public virtual IList<OrderItem> Items { get; set; }
}

public class OrderItem : Entity
{
    public virtual decimal Price {get; set;}
    public virtual string ItemNumber {get; set;}
    public virtual OrderHeader Header {get; set;}
}

public class OrderHeaderMap : ClassMap<OrderHeader>
{
    Id( e => e.Id).GeneratedBy.Native();
    HasMany(e => e.OrderItems).Inverse();
}

public class OrderItemMap : ClassMap<OrderItem>
{
    Id(e => e.Id).GeneratedBy.Native();
    References(e => e.Header).Not.Nullable();
}

As you can see the OrderHeader has an IList of items. Changing this to

public class OrderHeader : Entity
{
    public virtual ISet<OrderItem> Items { get; set; } // ISet here
}

public class OrderItem : Entity
{
    public virtual decimal Price {get; set;}
    public virtual string ItemNumber {get; set;}
    public virtual OrderHeader Header {get; set;}
}

public class OrderHeaderMap : ClassMap<OrderHeader>
{
    Id( e => e.Id).GeneratedBy.Native();
    HasMany(e => e.OrderItems).Inverse();
}

public class OrderItemMap : ClassMap<OrderItem>
{
    Id(e => e.Id).GeneratedBy.Native();
    References(e => e.Header).Not.Nullable().AsSet(); // Explicit AsSet
}

So an ISet and the explicit AsSet() on the mapping made the issue go away. This code snippet is very simplified and we had multiple entities in the QueryOver with HasMany() IList - when all were updated to the ISet, it worked properly.

I wouldn't worry too much about the hbm itself. FluentNHibernate "compiles" to XML which goes through the mapping layer. NHibernate's own mapping-by-code also uses parts of the same code as hbm files.

Anyway, the mapping code hasn't changed very much. Any regressions are more likely to be in other parts.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!