سؤال

أحاول الاستعلام عن خاصية IList<string> في إحدى فئات المجال الخاصة بي باستخدام NHibernate.فيما يلي مثال بسيط للتوضيح:

public class Demo
{
    public Demo()
    {
        this.Tags = new List<string>();
    }
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<string> Tags { get; set; }
}

تم تعيينه على النحو التالي:

<class name="Demo">
<id name="Id" />
<property name="Name" />
<bag name="Tags">
  <key column="DemoId"/>
  <element column="Tag" type="String" />
</bag>

وأنا قادر على الحفظ والاسترجاع بشكل جيد.الآن للاستعلام عن مثيلات فئة المجال الخاصة بي حيث تحتوي خاصية العلامات على قيمة محددة:

var demos = this.session.CreateCriteria<Demo>()
            .CreateAlias("Tags", "t")
            .Add(Restrictions.Eq("t", "a"))
            .List<Demo>();

النتائج في الخطأ:لم تكن المجموعة جمعية:العلامات التجريبية

var demos = (from d in this.session.Linq<Demo>()
                     where d.Tags.Contains("a")
                     select d).ToList();

النتائج في الخطأ:لم يتم تعيين مرجع Objct لمثيل كائن.

var demos = this.session.CreateQuery("from Demo d where :t in elements(d.Tags)")
            .SetParameter("t", "a")
            .List<Demo>();

يعمل بشكل جيد، ولكن نظرًا لأن فئة المجال الحقيقي الخاصة بي تحتوي على العديد من الخصائص، وأنا أقوم ببناء استعلام ديناميكي معقد، فإن القيام بمعالجة السلسلة القبيحة ليس خياري الأول.أفضل استخدام ICriteria أو Linq.لدي واجهة مستخدم حيث يمكن إدخال العديد من معايير البحث المختلفة الممكنة.الكود الذي يبني ICriteria الآن يتكون من عشرات الأسطر.أنا أكره حقًا تحويل ذلك إلى معالجة سلسلة HQL.

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

المحلول

وهكذا بسبب القيود المفروضة على API المعايير، قررت لثني الطبقات نطاقي لتناسب.

وأنا خلقت طبقة كيان للعلامة. لم أستطع حتى إنشائه ككائن القيمة. وكان لديك معرف الخاص بها.

وأشعر القذرة الآن. ولكن القدرة على بناء استعلام الحيوي دون اللجوء إلى التلاعب سلسلة كان أكثر أهمية بالنسبة لي من البقاء وفيا لالمجال.

نصائح أخرى

كما هو موثق هنا:

17.1.4.1.الاسم المستعار ومراجع الملكية

يمكننا ان نستخدم:

...
A collection key             {[aliasname].key}      ORGID as {coll.key}
The id of an collection      {[aliasname].id}       EMPID as {coll.id}
The element of an collection {[aliasname].element}  XID as {coll.element}
...

هناك خطأ صغير في الوثيقة ...بدلاً من ".element" علينا أن نستخدم ".elements"

var demos = this.session.CreateCriteria<Demo>()
        .CreateAlias("Tags", "t")

        // instead of this
        // .Add(Restrictions.Eq("t", "a"))

        // we can use the .elements keyword
        .Add(Restrictions.Eq("t.elements", "a"))

        .List<Demo>();

وتحتاج إلى استخدام SubCriterias لا الاسم المستعار. هذا يجب أن تعمل:

var demos = this.session.CreateCriteria<Demo>()
            .CreateCriteria("Tags")
            .Add(Restrictions.Eq("Tag", "a"))
            .List<Demo>();

وHQL:

from Demo d where :val in elements(d.Tags)

والتبديل إلى فئة أكثر من سلسلة هو حل وسط واحد. باستخدام HQL بدلا من ICriteria شيء آخر. هناك حلا وسطا الثالث ولكن ... استخدام SQL مخصصة. جرب هذا.

var demos = Session.CreateCriteria<Demo>()
    .Add(Expression.Sql(
        "EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = {alias}.[Id] AND custom_sql_t.[Tag] = ?)",
        "a",
        NHibernateUtil.String))
    .List<Demo>();

وهذا يؤدي إلى SQL follwing التي تولدها NHibernate 2.1.2.4000 ...

exec sp_executesql N'SELECT this_.Id as Id2_0_, this_.Version as Version2_0_, this_.Name as Name2_0_ FROM Demo this_ WHERE EXISTS (SELECT 1 FROM [Tags] custom_sql_t WHERE custom_sql_t.[DemoId] = this_.[Id] AND custom_sql_t.[Tag] = @p0)',N'@p0 nvarchar(1)',@p0=N'a'

وانظر هذا المنصب لمثال آخر ...

NHibernate - الاستعلام عن من مجموعة من أنواع القيمة (غير الكيان) لحل اختر N + 1

وهذا ممكن عن طريق خلق معايير منفصلة:

ICriteria demoCriteria = session.CreateCriteria<Demo>();
...
demoCriteria.Add(Restrictions...);
...
ICriteria tagCriteria = demoCriteria.CreateCriteria("Tags");
tagCriteria.Add(Restrictions.In("elements", new {"Tag1", "Tag2", ...}));

return demoCriteria.List<Demo>();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top