2011-01-06 10 views
44

मैं इस भंडार विधिnHibernate और QueryOver API के साथ एक अलग परिणाम कैसे प्राप्त करें?

public IList<Message> ListMessagesBy(string text, IList<Tag> tags, int pageIndex, out int count, out int pageSize) 
    { 
     pageSize = 10; 
     var likeString = string.Format("%{0}%", text); 
     var query = session.QueryOver<Message>() 
      .Where(Restrictions.On<Message>(m => m.Text).IsLike(likeString) || 
      Restrictions.On<Message>(m => m.Fullname).IsLike(likeString)); 

     if (tags.Count > 0) 
     { 
      var tagIds = tags.Select(t => t.Id).ToList(); 
      query 
       .JoinQueryOver<Tag>(m => m.Tags) 
       .WhereRestrictionOn(t => t.Id).IsInG(tagIds); 
     }    

     count = 0; 
     if(pageIndex < 0) 
     { 
      count = query.ToRowCountQuery().FutureValue<int>().Value; 
      pageIndex = 0; 
     } 
     return query.OrderBy(m => m.Created).Desc.Skip(pageIndex * pageSize).Take(pageSize).List(); 
    } 

तुम एक मुक्त पाठ खोज स्ट्रिंग और की टैग एक सूची की आपूर्ति की है। समस्या यह है कि यदि किसी संदेश में एक टैग होता है तो एक टैग को डुप्लीकेट बार सूचीबद्ध किया जाता है। मुझे संदेश इकाई के आधार पर एक विशिष्ट परिणाम चाहिए। मैंने

Projections.Distinct 

पर देखा है लेकिन इसके लिए विशिष्ट प्रश्नों के लिए गुणों की एक सूची की आवश्यकता है। यह संदेश मेरी इकाई रूट है, जिसमें अधिकांश इकाई गुणों की आपूर्ति किए बिना इस व्यवहार को प्राप्त करने का एक तरीका है?

अग्रिम धन्यवाद, ऐन्डर्स

उत्तर

61

आप ICriteria एपीआई का उपयोग कर रहे हैं, तो आप की जरूरत है:

.SetResultTransformer(new DistinctEntityRootTransformer()) 

आप QueryOver एपीआई का उपयोग कर रहे हैं, तो आप की जरूरत है:

.TransformUsing(Transformers.DistinctRootEntity) 

लेकिन सावधान रहें, यह सब क्लाइंट पक्ष पर होता है, इसलिए सभी डुप्लिकेट पंक्तियां अभी भी खींची जाती हैं।

tags.SelectList(t => t.SelectGroup(x => x.Id)) 

काम करना चाहिए और के रूप में विशिष्ट समान क्वेरी योजना का उत्पादन: इस

public IPagedList<Client> Find(int pageIndex, int pageSize) 
{ 
    Client clientAlias = null; 

    var query = Session.QueryOver<Client>(() => clientAlias) 

     .Select(
      Projections.Distinct(
       Projections.ProjectionList() 
        .Add(Projections.Property<Client>(x => x.Id).As("Id")) 
        .Add(Projections.Property<Client>(x => x.Name).As("Name")) 
        .Add(Projections.Property<Client>(x => x.Surname).As("Surname")) 
        .Add(Projections.Property<Client>(x => x.GivenName).As("GivenName")) 
        .Add(Projections.Property<Client>(x => x.EmailAddress).As("EmailAddress")) 
        .Add(Projections.Property<Client>(x => x.MobilePhone).As("MobilePhone")) 
      ) 
     ) 
     .TransformUsing(Transformers.AliasToBean<Client>()) 

     .OrderBy(() => clientAlias.Surname).Asc 
     .ThenBy(() => clientAlias.GivenName).Asc; 

    var count = query 
     .ToRowCountQuery() 
     .FutureValue<int>(); 

    return query 
     .Take(pageSize) 
     .Skip(Pagination.FirstResult(pageIndex, pageSize)) 
     .List<Client>() 
     .ToPagedList(pageIndex, pageSize, count.Value); 
} 
+5

आईसीआरटीरिया एपीआई QUeryOver के साथ बहुत धाराप्रवाह नहीं है, लेकिन। ट्रांसफॉर्मिंग (ट्रांसफॉर्मर्स.डिस्टिंट रूट एंटीटी); सही काम करता है। – Anders

+0

.TransformUsing (ट्रांसफॉर्मर्स। डिस्टिंट रूट एंटीटी) पेजिंग के साथ बिल्कुल काम नहीं किया:/कोई अन्य विचार? – Anders

+7

यह पेजिंग के साथ काम नहीं करेगा। पेजिंग प्रश्नों के लिए आपको अनुमानों का उपयोग करने की आवश्यकता होगी – Sly

25

कोशिश कुछ। मैं हाल ही में एक विधि बनाया है एक मैप की गई वस्तु प्रकार के आधार पर चयन अलग लागू करने के लिए

tags.SelectList(t => t.SelectGroup(x => x.Id) 
         .SelectGroup(x => x.Name) 
       ) 
+6

काम करता है लेकिन ... थकाऊ। इसके बजाय ("xxx") आप थोड़ी कम जादू तारों के लिए WithAlias ​​एक्सटेंशन विधि को कॉल कर सकते हैं। धन्यवाद – Sam

+0

WithAlias ​​एक्सटेंशन विधि उदाहरण: .WithAlias ​​(() => entity.PropertyName) – xhafan

10

आप selectList और GroupBy, उदा उपयोग कर सकते हैं की तरह

0

:

आप समूह में अनेक आइटम की जरूरत है, की तरह कुछ है। यह इसे IQueryOver ऑब्जेक्ट (कक्षा की संपत्ति) पर लागू करता है। विधि को निबर्ननेट कॉन्फ़िगरेशन तक पहुंच भी है। आप इन्हें विधि पैरामीटर के रूप में जोड़ सकते हैं। उत्पादन के लिए काम की ज़रूरत है, लेकिन विधि देव में महान काम कर रही है, केवल इसे एक इकाई के लिए इस्तेमाल किया जाता है।

यह विधि इसलिए बनाई गई थी क्योंकि मैं सर्वर स्तर पर अपना डेटा पेज करने की कोशिश कर रहा हूं और एक अलग परिणाम ट्रांसफॉर्मर काम नहीं करेगा।

आपके ऑब्जेक्ट संग्रह (क्वेरी.लिस्ट()) प्राप्त करने के बाद आपको ऑब्जेक्ट को फिर से लोड करना पड़ सकता है ताकि कई बच्चे ऑब्जेक्ट्स में से एक को पॉप्युलेट किया जा सके। आलसी लोड के लिए कई मैपिंग्स को प्रॉक्सी किया जाएगा।

public void DistinctRootProjectionList<E>() 
    { 
     var classMapping = Context.Config.GetClassMapping(typeof(E)); 
     var propertyIterator = classMapping.UnjoinedPropertyIterator; 
     List<IProjection> projections = new List<IProjection>(); 
     ProjectionList list = Projections.ProjectionList(); 

     list.Add(Projections.Property(classMapping.IdentifierProperty.Name), classMapping.IdentifierProperty.Name); 

     foreach (var item in propertyIterator) 
     { 
      if (item.Value.IsSimpleValue || item.Value.Type.IsEntityType) 
      { 
       list.Add(Projections.Property(item.Name), item.Name); 
      } 
     } 
     query.UnderlyingCriteria.SetProjection(Projections.Distinct(list)); 
     query.TransformUsing(Transformers.AliasToBean<E>()); 
    } 

कोड मैं कई संबंधों में से एक लोड करता था ... टी इकाई प्रकार है।

for (int i = 0; i < resp.Data.Count; i++) 
     { 
      resp.Data[i] = session.Load<T>(GetInstanceIdValue(resp.Data[i])); 
     } 
संबंधित मुद्दे