سؤال

باستخدام nhibernate أحاول الحصول على قائمة من B's حيث تحتوي خاصية IList لـ B على مثيل محدد لـ A.

نأمل أن يفسر الرمز التالي الموقف بشكل أكثر وضوحًا:

public void test()
{
    A a1 = new A();
    A a2 = new A();
    B b1 = new B();
    b1.As = new List<A> { a1 };
    // ...database save cut...

    using (ISession session = SessionFactory.OpenSession())
    {
        var result1 = session.CreateCriteria<B>()
            .CreateAlias("As", "a_As")
            .Add(Restrictions.Eq("a_As.ID", a1.ID))
            .List();

        var result2 = session.CreateCriteria<B>()
            .CreateAlias("As", "a_As")
            .Add(Restrictions.Eq("a_As", a1))
            .List();
    }
}

class A
{
    public virtual int ID { get; set; }
}

class B
{
    public virtual IList<A> As { get;set;}
}

فشل الاستعلام الثاني مع الخطأ: could not resolve property: a_As of: B

كيف يمكنني إجراء هذا الاستعلام باستخدام مثيلات الكائن دون استخدام خصائص المعرف بشكل صريح كما في الاستعلام الأول أعلاه.

تحرير: للتوسع في هذا ، لدي فئة عامة تؤدي عمليات nhibernate مع كياناتاتي. لقد قمت للتو بإنشاء طريقة "isreference" تبدأ على النحو التالي:

public bool IsReferenced(T entity)
{
    // Get the types (and their properties) that reference the type in question
    var typeProps = from type in typeof(T).Assembly.GetTypes()
                    let props = type.GetProperties().Where(p => p.PropertyType == typeof(T)).Select(p => p.Name)
                    let collections = type.GetProperties().Where(p => typeof(IEnumerable<T>).IsAssignableFrom(p.PropertyType)).Select(p => p.Name)
                    where type.IsClass && !type.IsAbstract && ((props != null && props.Count() > 0) || (collections != null && collections.Count() > 0))
                    select new { EntityType = type, Properties = props, Collections = collections };

    var multiCriteria = NHibernateSession.CreateMultiCriteria();
    foreach (var typeProp in typeProps)
    {
        var criteria = NHibernateSession.CreateCriteria(typeProp.EntityType);
        var disjunction = new Disjunction();
        foreach (var propName in typeProp.Properties)
        {
            disjunction.Add(Restrictions.Eq(propName, entity));
        }
        foreach (var collectionName in typeProp.Collections)
        {
            throw new NotImplementedException();
        }
        criteria.Add(disjunction);
        multiCriteria.Add(criteria);
    }
.....
}

أنا أستخدم TypeProps لإنشاء متعددة المعايير للعثور على أي كيانات في أي مكان تشير إلى تلك المحددة. إنه يعمل بشكل جيد للخصائص العادية ، لكن خصائص التجميع تمنحني الحزن. لست متأكدًا من كيفية إضافة التقييد إلى المعايير.

هل كانت مفيدة؟

المحلول 2

لقد وجدت حلاً يبدو أنه يعمل مع جميع الكيانات الحالية الخاصة بي ، استنادًا إلى قطعتين من المعلومات التي قمت بها أثناء العمل على هذا:

  • تنص الوثائق على أن "معرف" الحالات المنخفضة هو خاصية خاصة يمكن استخدامها للإشارة إلى معرف أي كيان.
  • يعرض Isession طريقة عامة object ISession.GetIdentifier(object obj)

هذان الحزمان دعونا نفعل شيئًا كهذا:

var result2 = session.CreateCriteria<B>()
        .CreateAlias("As", "a_As")
        .Add(Restrictions.Eq("a_As.id", session.GetIdentifier(a1)))
        .List();

والطريقة الناتجة الناتجة تبدو هكذا:

    public bool IsReferenced(T entity)
    {
        // Get the types (and their properties) that reference the type in question
        var typeProps = from type in typeof(T).Assembly.GetTypes()
                        let props = type.GetProperties().Where(p => p.PropertyType == typeof(T)).Select(p => p.Name)
                        let collections = type.GetProperties().Where(p => typeof(IEnumerable<T>).IsAssignableFrom(p.PropertyType)).Select(p => p.Name)
                        where type.IsClass && !type.IsAbstract && ((props != null && props.Count() > 0) || (collections != null && collections.Count() > 0))
                        select new { EntityType = type, Properties = props, Collections = collections };

        var multiCriteria = NHibernateSession.CreateMultiCriteria();

        // Create a big or query to test whether any of the properties are, or contain, the entity parameter
        foreach (var typeProp in typeProps)
        {
            var criteria = NHibernateSession.CreateCriteria(typeProp.EntityType);
            var disjunction = new Disjunction();
            foreach (var propName in typeProp.Properties)
            {
                disjunction.Add(Restrictions.Eq(propName, entity));
            }
            foreach (var collectionName in typeProp.Collections)
            {
                string alias = string.Format("a_{0}", collectionName);
                criteria.CreateAlias(collectionName, alias, NHibernate.SqlCommand.JoinType.LeftOuterJoin);

                disjunction.Add(Restrictions.Eq(string.Format("{0}.id", alias), NHibernateSession.GetIdentifier(entity)));
            }
            criteria.Add(disjunction);
            multiCriteria.Add(criteria);
        }

        var results = multiCriteria.List();

        bool hasReferences = false;
        foreach (var resultSet in results)
        {
            if ((resultSet as System.Collections.IList).Count != 0)
            {
                hasReferences = true;
                break;
            }
        }
        return hasReferences;
    }

إذا كان عقلي قد بدأ فقط قبل أن أضع نصف سمعتي كمكافأة ...

نصائح أخرى

يتم تقديم هذا النوع من الاستعلام بشكل أفضل بواسطة HQL من المعايير:

session.CreateQuery("from B b where :a in elements(b.As)")
       .SetParameter("a", a1)
       .List();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top