【问题标题】:Selecting an entity with multiple child entities选择具有多个子实体的实体
【发布时间】:2011-08-25 05:53:47
【问题描述】:

使用 Active Record/NHibernate,我正在尝试选择一个具有多个子集合的实体(站点)。

只有一个具有给定 siteId 的站点,但 FindAll 会返回该站点 28 次;由于正在加载子集合,它被复制了。如何让它只加载 1 个站点和子集合的数组?我不介意它是否进行 5 次选择,一次抓取网站,然后每个子集合 1 次。

代码如下:

var criteria = DetachedCriteria.For<Site>()
                    .CreateAlias("TimeZone", "tz", NHibernate.SqlCommand.JoinType.InnerJoin)
                    .CreateAlias("Logos", "l", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .CreateAlias("SiteColors", "sc", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .CreateAlias("ManagerUsers", "mu", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
                    .Add(Restrictions.Eq("Id", siteId));
                var sites = FindAll(criteria);

我应该提到我也尝试了使用 fetch 的 hql 方法,但是 fetch 没有获取!它只返回一个站点(好),但没有一个子集合被急切加载(坏)。

public static Site Get(int id)
        {
            var query = new SimpleQuery<Site>(@"
                from Site s
                where s.Id = ?
                inner join fetch s.TimeZone tc
                left join fetch s.Logos l
                left join fetch s.SiteColors sc
                left join fetch s.ManagerUsers mu
            ", id);
            var results = query.Execute().ToList();
            return results.FirstOrDefault();
        }

这是使用“未来”方法的代码似乎有效:

public static Site Get(int id)
        { 
            var session = ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(Site));
            var query = session.CreateQuery("from Site s left join fetch s.Logos where s.Id = :id").SetParameter("id", id).Future<Site>();
            session.CreateQuery("from Site s left join fetch s.SiteColors where s.Id = :id2").SetParameter("id2", id).Future<Site>();
            session.CreateQuery("from Site s left join fetch s.ManagerUsers where s.Id = :id3").SetParameter("id3", id).Future<Site>();
            return query.FirstOrDefault();
        }

我所有的数据模型类都继承自 SimpleModel 类,我已将 Equals 和 GetHashCode 方法添加到:

public abstract class SimpleModel
    {
        protected SimpleModel()
        {
            DateCreated = DateTimeAccess.Now;
        }

        [PrimaryKey]
        [DocumentId]
        public virtual int Id { get; set; }

        [Property]
        public virtual DateTime DateCreated { get; set; }

        public override bool Equals(object obj)
        {
            if (obj is SimpleModel)
            {
                return Id.Equals(((SimpleModel)obj).Id);
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
    }

【问题讨论】:

    标签: nhibernate activerecord castle-activerecord


    【解决方案1】:

    根据您的标准致电SetResultTransformer(DistinctRootEntity)。它会将那些重复的 Site 实例折叠为单个实例。

    有关更多信息,请参阅此主题:http://groups.google.com/group/nhusers/browse_thread/thread/9919812230702ccc

    【讨论】:

    • 谢谢@Mauricio。哪种方法更好,使用 SetResultTransformer 还是创建新会话并使用 Future 方法加入多个查询?
    • 这种方法似乎不起作用,它强制只有一个根实体,这很好,但是它复制了子实体。例如,我的一个子集合应该有 21 个对象,而不是现在有 315 个。
    • @Justin:确保你已经正确实现了 GetHashCode() 和 Equals()
    • @Mauricio:您能否对此进行更多解释或提供链接?我曾经实现 GetHashCode() 和 Equals() 的唯一原因是我有一个复合主键,而这里不是这种情况。
    • @Justin:这不仅适用于复合 PK。从这里开始:derickbailey.com/2008/03/24/…
    猜你喜欢
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多