0

ドメイン

クエリを最適化しようとしていますが、アドバイスが必要です。これは、1対多の関係を照会するための好ましい方法ですか?

私のドメインは次のようになります。

MeasureSet

   /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// Tables: none
    /// </remarks>
    public class MeasureSet : PersistentEntity
    {
        #region Properties
        /// <summary>
        /// Gets or sets the code.
        /// </summary>
        /// <value>
        /// The code.
        /// </value>
        public virtual string Code { get; set; }
        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public virtual string Description { get; set; }
        /// <summary>
        /// Gets or sets the measure domains.
        /// </summary>
        /// <value>
        /// The measure domains.
        /// </value>
        public virtual IList<MeasureDomain> MeasureDomains { get; protected set; } 
}

MeasureDomain

   /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// Tables: domeinen
    /// </remarks>
    public class MeasureDomain : PersistentEntity
    {
        #region Properties
        /// <summary>
        /// Gets or sets the code.
        /// </summary>
        /// <value>
        /// The code.
        /// </value>
        public virtual string Code { get; set; }
        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public virtual string Description { get; set; }
        /// <summary>
        /// Gets or sets the explanation.
        /// </summary>
        /// <value>
        /// The explanation.
        /// </value>
        public virtual string Explanation { get; set; }
        /// <summary>
        /// Gets or sets the measure set.
        /// </summary>
        /// <value>
        /// The measure set.
        /// </value>
        public virtual MeasureSet MeasureSet { get; set; }
        /// <summary>
        /// Gets or sets the measure sub domains.
        /// </summary>
        /// <value>
        /// The measure sub domains.
        /// </value>
        public virtual IList<MeasureSubDomain> MeasureSubDomains { get; protected set; }
        /// <summary>
        /// Gets or sets the audits.
        /// </summary>
        /// <value>
        /// The audits.
        /// </value>
        public virtual IList<Audit> Audits { get; protected set; } 
        #endregion
}

MeasureSubDomain

   /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// Tables: subdomeinen, subdomeinenbestanden
    /// </remarks>
    public class MeasureSubDomain : PersistentEntity
    {
        #region Properties
        /// <summary>
        /// Gets or sets the code.
        /// </summary>
        /// <value>
        /// The code.
        /// </value>
        public virtual string Code { get; set; }
        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public virtual string Description { get; set; }
        /// <summary>
        /// Gets or sets the domain.
        /// </summary>
        /// <value>
        /// The domain.
        /// </value>
        public virtual MeasureDomain MeasureDomain { get; set; }
        /// <summary>
        /// Gets or sets the explanation.
        /// </summary>
        /// <value>
        /// The explanation.
        /// </value>
        public virtual string Explanation { get; set; }
        /// <summary>
        /// Gets or sets the files.
        /// </summary>
        /// <value>
        /// The files.
        /// </value>
        public virtual IList<File> Files { get; protected set; }
        /// <summary>
        /// Gets or sets the measure controls.
        /// </summary>
        /// <value>
        /// The measure controls.
        /// </value>
        public virtual IList<MeasureControl> MeasureControls { get; protected set; }
        /// <summary>
        /// Gets or sets the audits.
        /// </summary>
        /// <value>
        /// The audits.
        /// </value>
        public virtual IList<Audit> Audits { get; protected set; }
}

必要なのは、子のコレクション、CodeプロパティとDescriptionプロパティだけです。私が現在使用しているクエリは次のとおりです。

1対多のクエリ

 measureSets = LazySessionFactory.CurrentSession.CreateCriteria<MeasureSet>()
        .Add(Subqueries.PropertyIn("Id",
            DetachedCriteria.For<MeasureDomain>()
                .SetProjection(Projections.Property("MeasureSet.Id"))
                .Add(Subqueries.PropertyIn("Id",
                    DetachedCriteria.For<MeasureSubDomain>()
                    .SetProjection(Projections.Property("MeasureDomain.Id"))
                    .Add(Subqueries.PropertyIn("Id",
                        DetachedCriteria.For<MeasureControl>()
                        .SetProjection(Projections.Property("MeasureSubDomain.Id"))
                        .Add(Subqueries.PropertyIn("Id",
                            DetachedCriteria.For<Measure>()
                            .SetProjection(Projections.Property("MeasureControl.Id"))))))))))
                            .SetCacheable(true)
                            .Future<MeasureSet>().ToList();

基本クラス

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GRCcontrol.Domain.Entities
{
    /// <summary>
    /// Base class for domain entities based on NHibernate.
    /// </summary>
    /// <typeparam name="TId">The type of the id.</typeparam>
    public abstract class PersistentEntity<TId> : IEquatable<PersistentEntity<TId>>
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>
        /// The id.
        /// </value>
        public virtual TId Id { get; protected set; }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            return Equals(obj as PersistentEntity<TId>);
        }
        /// <summary>
        /// Determines whether the specified obj is transient.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>
        ///   <c>true</c> if the specified obj is transient; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsTransient(PersistentEntity<TId> obj)
        {
            return obj != null &&
                Equals(obj.Id, default(TId));
        }
        /// <summary>
        /// Gets the type of the unproxied type, since NHibernate's lazy loading technology, creates proxies from entities.
        /// </summary>
        /// <returns></returns>
        private Type GetUnproxiedType()
        {
            return GetType();
        }
        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        /// <param name="other">The other.</param>
        /// <returns></returns>
        public virtual bool Equals(PersistentEntity<TId> other)
        {
            if (other == null)
                return false;
            if (ReferenceEquals(this, other))
                return true;
            if (!IsTransient(this) &&
                !IsTransient(other) &&
                Equals(Id, other.Id))
            {
                var otherType = other.GetUnproxiedType();
                var thisType = GetUnproxiedType();

                return thisType.IsAssignableFrom(otherType) ||
                    otherType.IsAssignableFrom(thisType);
            }

            return false;
        }
        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            if (Equals(Id, default(TId)))
                return base.GetHashCode();

            return Id.GetHashCode();
        }
    }
    /// <summary>
    /// Base class for domain entities based on NHibernate.
    /// </summary>
    public abstract class PersistentEntity : PersistentEntity<Guid>
    {
    }
}

私はまだすべてのプロパティを取得しているので、現時点では実際には必要のない監査などのコレクションも取得しています。NHibernateはコレクションのプロジェクションをサポートしていないため、パフォーマンスを向上させるためにコードをどのように変更する必要があるのか​​疑問に思っています。

あなたが私を助けてくれることを願っています。

4

2 に答える 2

0

私はあなたが本当に欲しいのは熱心なフェッチだと思います:

measureSets = LazySessionFactory.CurrentSession.CreateCriteria<MeasureSet>()
    .SetFetchMode("MeasureDomains", FetchType.Eager)
    .SetFetchMode("MeasureDomains.MeasureSubDomains", FetchType.Eager)
    .SetFetchMode("MeasureDomains.MeasureSubDomains.MeasureControls", FetchType.Eager)
    .SetCacheable(true)
    .Future<MeasureSet>().ToList();

ドメイン/サブドメイン/コントロールを持たないメジャーセットを除外しないことを除いて、ほとんどあなたが望むことをします

これが十分でない場合は、次を追加して制限できます。

measureSets = LazySessionFactory.CurrentSession.CreateCriteria<MeasureSet>()
    .Add(Subqueries.PropertyIn("Id", 
        DetachedCriteria.For<Measure>()
            .CreateAlias("MeasureControl", "mc")
            .CreateAlias("mc.MeasureSubDomain", "msd")
            .CreateAlias("msd.MeasureDomain", "md")
            .SetProjection(Projections.Property("md.MeasureSet.id")))
    .SetFetchMode("MeasureDomains", FetchType.Eager)
    .SetFetchMode("MeasureDomains.MeasureSubDomains", FetchType.Eager)
    .SetFetchMode("MeasureDomains.MeasureSubDomains.MeasureControls", FetchType.Eager)
    .SetCacheable(true)
    .Future<MeasureSet>().ToList();

(モデルの残りの部分についていくつかの仮定をしました)ただし、これには、パフォーマンスを低下させる可能性のある副選択が必要になるという欠点があります(YMMV)

于 2013-02-21T15:14:48.380 に答える
0

私はこの問題に数時間を費やしましたが、最終的に解決策を見つけました。このクエリも最適化されており、データベースを4回呼び出す必要があります。

    IEnumerable<MeasureSet> measureSets = null;

    var currentSession = LazySessionFactory.CurrentSession;

    measureSets = currentSession.QueryOver<MeasureSet>().TransformUsing(Transformers.DistinctRootEntity)
        .Fetch(m => m.MeasureDomains).Eager
        .Future();

    var setIds = measureSets.Select(x => x.Id).ToArray();

    var domains = currentSession.QueryOver<MeasureDomain>().TransformUsing(Transformers.DistinctRootEntity)
        .WhereRestrictionOn(x => x.MeasureSet.Id).IsIn(setIds).Fetch(m => m.MeasureSubDomains).Eager.Future();
    var domainIds = domains.Select(x => x.Id).ToArray();

    var subDomains = currentSession.QueryOver<MeasureSubDomain>().TransformUsing(Transformers.DistinctRootEntity)
        .WhereRestrictionOn(x => x.MeasureDomain.Id).IsIn(domainIds).Fetch(m => m.MeasureControls).Eager.Future();
    var subDomainIds = subDomains.Select(x => x.Id).ToArray();

    var controls = currentSession.QueryOver<MeasureControl>().TransformUsing(Transformers.DistinctRootEntity)
        .WhereRestrictionOn(x => x.MeasureSubDomain.Id).IsIn(subDomainIds).Fetch(m => m.Measures).Eager.Future();
    var controlIds = controls.Select(x => x.Id).ToArray();

    currentSession.QueryOver<Measure>().TransformUsing(Transformers.DistinctRootEntity)
        .WhereRestrictionOn(x => x.MeasureControl.Id).IsIn(controlIds).Future();

    return measureSets.AsQueryable();

これよりも良い解決策があれば、私の答えに答えてください。

于 2013-02-26T06:34:13.927 に答える