2010-10-29 11 views
5

मेरा वर्तमान प्रोजेक्ट NHibernate 3.0b1 और NHibernate.Linq.Query<T>() API का उपयोग कर रहा है। मैं LINQ में बहुत स्पष्ट हूं, लेकिन मुझे एचक्यूएल या आईसीआरटीरिया एपीआई के साथ बिल्कुल कोई अनुभव नहीं है। मेरे प्रश्नों में से एक IQueryable API द्वारा समर्थित नहीं है, इसलिए मुझे लगता है कि मुझे पिछले एपीआई में से किसी एक का उपयोग करने की आवश्यकता है - लेकिन मुझे नहीं पता कि कहां से शुरू करना है।एनएचबीर्नेट आईसीआरटीरिया एपीआई का उपयोग करके मैं इस LINQ क्वेरी को कैसे व्यक्त करूं?

मैं ICriteria के लिए एक अच्छा "शुरू हो रही है" गाइड के लिए वेब की खोज करने की कोशिश की है, लेकिन केवल उदाहरण मैंने पाया या तो अभी तक बहुत साधारण यहाँ या अभी तक बहुत उन्नत मुझे समझने के लिए लागू करने के लिए कर रहे हैं। अगर किसी के साथ पास करने के लिए कुछ अच्छी शिक्षा सामग्री है, तो इसकी सराहना की जाएगी।

किसी भी मामले में, ऑब्जेक्ट मॉडल मैं इस तरह दिखता है के खिलाफ की क्वेरी कर रहा हूँ (बहुत सरल बनाया, गैर प्रासंगिक गुण छोड़े गए):

class Ticket { 
    IEnumerable<TicketAction> Actions { get; set; } 
} 
abstract class TicketAction { 
    Person TakenBy { get; set; } 
    DateTime Timestamp { get; set; } 
} 
class CreateAction : TicketAction {} 
class Person { 
    string Name { get; set; } 
} 

एक Ticket अपने इतिहास का वर्णन TicketAction का संग्रह है। TicketAction उपप्रकारों में CreateAction, ReassignAction, CloseAction आदि शामिल हैं। सभी टिकटों में CreateAction बनाया गया है जब इस संग्रह में जोड़ा गया था।

यह LINQ क्वेरी किसी दिए गए नाम से किसी के द्वारा बनाए गए टिकटों की खोज कर रही है।

var createdByName = "john".ToUpper(); 
var tickets = _session.Query<Ticket>() 
    .Where(t => t.Actions 
     .OfType<CreateAction>() 
     .Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName)); 

OfType<T>() विधि एक NotSupportedException फेंक दिया करने के लिए कारण बनता है। क्या मैं इसके बजाय आईसीआरटीरिया का उपयोग कर ऐसा कर सकता हूं?

उत्तर

2

इस तरह कुछ कोशिश करें। यह असम्पीडित है, लेकिन इसे IEnumerable<TicketAction> Actions और Person TakenBy तक काम करना चाहिए जब तक कि यह शून्य न हो। यदि आप इसे टिकट कन्स्ट्रक्टर में एक खाली सूची में सेट करते हैं, तो यह नल के साथ एक समस्या का समाधान करेगा।

आप TicketAction में टिकट ऑब्जेक्ट के संदर्भ जोड़ते हैं तो आप कुछ इस तरह कर सकता है:

ICriteria criteria = _session.CreateCriteria(typeof(CreateAction)) 
    .Add(Expression.Eq("TakenBy.Name", createdByName)); 

var actions = criteria.List<CreateAction>(); 

var results = from a in criteria.List<>() 
    select a.Ticket; 

मेरे अनुभव में, nhibernate मापदंड के साथ परेशानी है जब इस सूची में दर्ज आता है जब सूची में है वस्तु पक्ष - जैसे आपका मामला है। जब यह इनपुट पक्ष पर मूल्यों की एक सूची है, तो आप Expression.Eq का उपयोग कर सकते हैं। मुझे हमेशा इस सीमा के चारों ओर linq के माध्यम से तरीकों को ढूंढना पड़ता है, जहां मुझे प्रारंभिक परिणाम सेट जितना संभव हो उतना फ़िल्टर किया जाता है, फिर मुझे जो चाहिए उसे प्राप्त करने के लिए linq के साथ फिर से फ़िल्टर करें।

+0

मैं नहीं बल्कि एक करने के लिए एक बैक-संदर्भ जोड़ने के लिए नहीं चाहते हैं 'टिकट' की 'टिकट 'अगर मैं इसकी मदद कर सकता हूं क्योंकि इससे अन्य समस्याएं शुरू होंगी, लेकिन टिप के लिए धन्यवाद। :) –

+0

इस तरह की स्थितियों को संभालने का दूसरा तरीका वास्तव में एक स्ट्रिंग बिल्डर में एचक्यूएल बनाना था। हमने लिंक को निबर्ननेट अभिव्यक्तियों का उपयोग करने का प्रयास किया, लेकिन जब संग्रह ऑब्जेक्ट पक्ष पर होता है तो वे भी संग्रह का समर्थन नहीं करते हैं। दुर्भाग्य से, "युक्त" विधि लिंक से nHibernate में अनुवाद नहीं करती है। – Josh

+0

मैं आपके सुझाव के साथ गया (टिकट पर टिकट के लिए संदर्भ जोड़ना), लेकिन मैं एक त्रुटि के साथ समाप्त होता हूं: "NHibernate.QueryException: संपत्ति को हल नहीं कर सका: TakenBy।का नाम: CreateAction " –

0

ऑफ़ टाइप टाइप किया गया है। मुझे यकीन नहीं है कि ToUpper हालांकि है, लेकिन एसक्यूएल मामले को अनदेखा करता है इससे कोई फर्क नहीं पड़ता (जब तक आप स्मृति में क्वेरी भी नहीं चला रहे हैं ...)। यहाँ nHibernate.LINQ परियोजना से एक काम इकाई परीक्षण है:

var animals = (from animal in session.Linq<Animal>() 
       where animal.Children.OfType<Mammal>().Any(m => m.Pregnant) 
       select animal).ToArray(); 
Assert.AreEqual("789", animals.Single().SerialNumber); 

शायद आपकी क्वेरी अधिक की तरह दिखना चाहिए निम्नलिखित:

var animals = (from ticket in session.Linq<Ticket>() 
       where ticket.Actions.OfType<CreateAction>().Any(m => m.TakenBy.Name.Contains("john")) 
       select ticket).ToArray();