【问题标题】:NHibernate return duplicate entities while parent is referenced by more than one propertyNHibernate 返回重复的实体,而父级被多个属性引用
【发布时间】:2014-06-05 18:03:15
【问题描述】:

环境:NHibernate(3.3.3.4001)、FluentNHibernate(1.4.0.0) 以下是 FluentNHibernate 映射:

public class CustomerMap : ClassMap<Customer>
        {
            public CustomerMap()
            {
                Id(x => x.Id);
                Map(x => x.Name).Not.Nullable();
                HasMany(x => x.Orders)
                    .KeyColumn("CustomerId")
                    .Cascade.All()
                    .LazyLoad(); 
                HasMany(x => x.Cards)
                    .KeyColumn("CustomerId")
                    .Cascade.All()
                    .LazyLoad();
            }
        }
        public class OrderMap:ClassMap<Order>
        {
            public OrderMap()
            {
                Id(x => x.Id);
                Map(x => x.OrderTime).Not.Nullable();
                References<Customer>(x => x.OrderOwner)
                    .LazyLoad().Column("CustomerId");
            }
        }
        public class CardMap:ClassMap<Card>
        {
            public CardMap()
            {
                Id(x => x.Id);
                Map(x => x.CardCode).Not.Nullable();
                References<Customer>(x => x.CardOwner)
                    .LazyLoad().Column("CustomerId");
            }
        }

实体:

public class Customer
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual IList<Order> Orders { get; set; }
            public virtual IList<Card> Cards { get; set; }
        }
        public class Order
        {
            public virtual int Id { get; set; }
            public virtual DateTime  OrderTime { get; set; }
            public virtual Customer OrderOwner { get; set; }
        }
        public class Card
        {
            public virtual int Id { get; set; }
            public virtual string CardCode { get; set; }
            public virtual Customer CardOwner { get; set; }
        }

现在在我的数据库中, 客户表

    Id  Name
    1   AAA
    2   BBB

订单表

    Id  OrderTime           CustomerId
    1   2014-04-20 00:48:52.110 1
    2   2014-04-20 00:48:52.110 2
    3   2014-04-20 00:49:01.403 1
    4   2014-04-20 00:49:01.403 1

牌桌

    Id  CardCode    CustomerId
    1   111 1
    2   111 2
    5   222 1
    6   333 1

当我使用 Criteria 和 FetchMode.Join 来获取惰性数据时,结果将包含重复的 Order 和属于 Customer 的 Card。 如Customer Id = 1,包含9(3×3)个Order对象和9(3×3)个Card对象

                   ISession session = FluentlyNHManager.OpenSession();
               ICriteria customerCriteria = session.CreateCriteria<Customer>()
                                            .SetFetchMode("Orders", FetchMode.Join)
                                            .SetFetchMode("Cards", FetchMode.Join)
                            .SetResultTransformer(Transformers.DistinctRootEntity);
               IList<Customer> customerList = customerCriteria.List<Customer>();

但是如果我使用HQL来获取数据,那是正确的。 Customer Id = 1 包含 3 个 Order 对象和 3 个 Card 对象

                   ISession session = FluentlyNHManager.OpenSession();
               ICriteria customerCriteria = session.CreateCriteria<Customer>(@"from Customer c left join fetch
Orders o left join fetch Cards c");          
               IList<Customer> customerList = customerCriteria.List<Customer>();

我可以编写什么代码来解决有关标准的问题?为什么结果错误?

【问题讨论】:

  • 我想我弄错了HQL,右边的HQL在下面,结果和Criteria一样:IQuery customerCriteria = session.CreateQuery(@"from Customer c left join fetch c.Orders o left加入 fetch c.Cards ca"); customerCriteria.SetResultTransformer(Transformers.DistinctRootEntity); IList customerList = customerCriteria.List();

标签: c# nhibernate fetch


【解决方案1】:

正如这篇有趣的阅读中提到的:Ayende - Eagerly loading entity associations efficiently with NHibernate:

似乎经常出现的一件事是人们急切地希望加载一个实体及其所有关联。当关联是多对一的(也就是说,每个根实体只有一个关联)时,这很容易做到。例如 Owner、Site 等。

...

当您尝试对多个集合关联执行相同操作时,问题就开始了。 NHibernate 允许您这样做,但结果可能不是您最初期望的...

有一些常用的方法,请查看:

详细的方法可以在这里找到:

注意:如果您已获取 child 和其他 child 并且... 不同的根转换 将无法完成这项工作,因为它只为一个根...

我的首选方式是:创建仅加入 many-to-one 引用的简单查询。让集合延迟加载,使用batch-size 功能(19.1.5. Using batch fetching

xml:

// class
<class name="ParentEntity" batch-size="25" lazy="true">
// collection
<bag name="Children" lazy="true" batch-size="25"

流利:

.BatchSize(25)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    相关资源
    最近更新 更多