6

मेरे पास एक IQueryable है जिसका एंटीटी फ्रेमवर्क 4 ऑब्जेक्ट्स मैं अपने डीटीओ समकक्षों को प्रोजेक्ट करना चाहता हूं। ऐसी एक वस्तु 'व्यक्ति' एक ईएफ 4 कक्षा है, और संबंधित पीओसीओ पर्सन एक कक्षा है जिसे मैंने परिभाषित किया है। मैं उनके बीच मैप करने के लिए ऑटोमैपर का उपयोग कर रहा हूं। हालांकि, जब मैं निम्नलिखित कोड का प्रयास करें:IQueryable Lambda प्रोजेक्शन सिंटेक्स

LINQ to Entities does not recognize the method 'TestSite.Models.PersonP Map[Person,PersonP](TestSite.DataLayer.Model.Person)' method, and this method cannot be translated into a store expression. 

उचित वाक्य रचना Automapper का उपयोग कर एक IQueryable<PersonP> प्रक्षेपण बनाने के लिए क्या है:

IQueryable<Person> originalModel = _repo.QueryAll(); 
IQueryable<PersonP> projection = originalModel.Select(e => Mapper.Map<Person, PersonP>(e)); 

प्रक्षेपण कार्यावधि में इस त्रुटि उत्पन्न करता है? धन्यवाद।

पीएस Automapper सही तरीके से कॉन्फ़िगर किया गया है - मैं इसे अन्य स्थानों में व्यक्ति और व्यक्ति के बीच आगे और पीछे बदलने के लिए उपयोग करता हूं, यानी Mapper.Map<Person, PersonP>(myPersonObject) सही ढंग से PersonP ऑब्जेक्ट देता है।

संपादित करें (अधिक कोड):

मैं एक Telerik ग्रिड को EF4 इकाई Pocos (PersonP) बाध्य करने के लिए एक सहायक समारोह के लिए इस का उपयोग कर रहा है - जो संस्थाओं खुद को क्रमानुसार नहीं होगा ठीक से बाद से वे परिपत्र शामिल संदर्भ (यानी नेविगेशन गुण)। मेरे कोड इस तरह दिखता है:

public static GridModel GetGridModel<TEntity, TPoco>(IRepository<TEntity> repo, GridState gridState) where TEntity : EntityObject 
{ 
var originalModel = repo.QueryAll().ToGridModel(gridState); 
var projection = originalModel.Select(e => Mapper.Map<TEntity, TPoco>(e)); 


return projection.ToGridModel(gridState); // applies filters, sorts, pages, etc... 
} 

.ToGridModel विधि IQueryable पर एक विस्तार विधि है और यह एक जटिल वस्तु जो मैं मज़बूती से पार्स नहीं कर सकता रिटर्न - तो यह मेरे मैं छानने मैं करने के बाद प्रदर्शन करने के लिए है का मानना ​​है की ओर जाता है पीओसीओ को प्रक्षेपण किया।

अद्यतन 2:

public static GridModel GetGridModel2(IRepository<Client> repo, GridState gridState) 
{ 
IQueryable<Client> originalModel = repo.QueryAll(); 
IQueryable<ClientP> projection = originalModel.Select(c => ClientToClientP(c)); 

return projection.ToGridModel(gridState); 
} 

private static ClientP ClientToClientP(Client c) 
{ 
return new ClientP { Id = c.Id, FirstName = c.FirstName }; 
} 

इस कोड को भी विफल रहता है जब प्रक्षेपण बनाने:

चीजों को आसान बनाने की कोशिश कर रहा, मैं इस तरह एक गैर सामान्य विधि बनाया है। मैंने देखा है कि IQueryable.Select() में एकाधिक अधिभार हैं: अभिव्यक्ति> उनमें से एक होना। क्या मैं इन अधिभारों में से किसी एक का उपयोग करके इस फ़ंक्शन/प्रतिनिधि कॉल का प्रतिनिधित्व कर सकता हूं?

उत्तर

5

Automapper का उपयोग करके IQueryable प्रोजेक्शन बनाने के लिए उचित वाक्यविन्यास क्या है?

कोई नहीं है। Automapper doesn't do this। यह नौकरी के लिए गलत उपकरण है।

कोई पूछताछ अनुमानों के लिए एक समान काम करने के लिए ऑटोमैपर-जैसी टूल बना सकता है। मैंने इसे अतीत में माना है, लेकिन हमेशा यह निष्कर्ष निकाला है कि इसका उपयोग करने वाला कोड प्रक्षेपण से कम पठनीय होगा। मैं कोड-रीडिंग समय पर कोड-लेखन समय अनुकूलित नहीं करना चाहता हूं।

आपका अपडेट किया गया कोड काम नहीं करता है क्योंकि यह अभिव्यक्ति नहीं है। यदि आप करते हैं:

private static Expression<Func<Client, ClientP>> ClientP ClientToClientP() 
{ 
    return c => new ClientP { Id = c.Id, FirstName = c.FirstName }; 
} 

...और फिर:

IQueryable<Client> originalModel = repo.QueryAll(); 
Expression<Func<Client, ClientP>> exp = ClientToClientP(); 
IQueryable<ClientP> projection = originalModel.Select(exp); 

... तो यह काम करेगा।

+0

यह ऑटोमैपर की बजाय नियमित विधि के साथ भी विफल रहता है। कृपया मेरी पोस्ट में UPDATED2 देखें। – Harper

+0

अपडेट देखें। गैर-अभिव्यक्तियों का अनुवाद एसक्यूएल में नहीं किया जा सकता है। –

+0

आपकी मदद के लिए धन्यवाद। आपका कोड काम करता है (विधि सिग में छोटे टाइपो को सही किया गया है) लेकिन जैसा कि आपने बताया है, ऑटोमैपर इस उद्देश्य के लिए अनुपयुक्त है और काम नहीं करता है। क्या आप तकनीकी कारणों की व्याख्या कर सकते हैं कि मैं एक ऑटोमैपर मैपिंग के लिए नए क्लाइंटपी {आईडी = ..} को प्रतिस्थापित क्यों नहीं कर सकता - क्योंकि दोनों क्लाइंट पी ऑब्जेक्ट लौटाते हैं? – Harper

2

यदि आप चयन से पहले .ToList() जोड़ते हैं तो आप सर्वर पक्ष (एसक्यूएल) के बजाय मैपिंग क्लाइंट-साइड (ऑब्जेक्ट्स के लिए लिंक) होने के लिए मजबूर कर सकते हैं। बस सुनिश्चित करें कि आपने पहले अपनी फ़िल्टरिंग की है ताकि आप पूरी तालिका को ऊपर नहीं ला रहे हैं।

+0

वैसे मैं वास्तव में फ़िल्टरिंग/समूह/सॉर्टिंग/आदि करने के लिए एक टेलीरिक विस्तार विधि का उपयोग कर रहा हूं और मैं इसे ईएफ क्वेरीरी पर लागू नहीं कर सकता क्योंकि ग्रिड उन संस्थाओं में परिपत्र निर्भरताओं को क्रमबद्ध नहीं कर सकता है। मैंने और कोड जोड़ा है। – Harper

+0

आप अज्ञात प्रकारों का उपयोग करके इकाइयों को मानचित्र बना सकते हैं: http://msdn.microsoft.com/en-us/library/bb738512.aspx लेकिन यह आपके पोको इकाइयों के बिंदु को याद करता है। ऐसा लगता है कि असली मुद्दा यहां है कि मोनोलिथिक 'ToGridModel' विधि को कॉल करें। वास्तव में इसे अलग करने की जरूरत है ताकि आप फिल्टर और सॉर्ट कर सकें, फिर प्रोजेक्ट कर सकें, फिर जो कुछ भी करने की ज़रूरत है उसे करें। क्या आप इसे अलग से फ़िल्टर लागू कर सकते हैं, फिर सीमा पार करें, फिर प्रोजेक्ट करें और ग्रिडमोडेल को इकट्ठा करें? –

+0

आपके सुझावों के लिए धन्यवाद। मैं जांच करूंगा कि क्या मैं ToGridModel() विधि को बाधित कर सकता हूं। – Harper

11

यह वास्तव में AutoMapper यहाँ के लेखक द्वारा अब हल किया गया है: http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/

वह एक कार्यान्वयन है कि एक वांछित प्रक्षेपण और क्वेरी लेता है और केवल प्रक्षेपण मानचित्रण के लिए आवश्यक क्षेत्रों के लिए डेटाबेस प्रश्नों प्रदान करता है।

इसके अलावा, कुछ कैशिंग सुधारों के लिए पॉल हिल्स द्वारा follow-on article देखें।

उम्मीद है कि इससे मदद मिलती है।

+0

बहुत उपयोगी, धन्यवाद। –

+0

इस पर आधिकारिक ऑटोमैपर दस्तावेज़: https://github.com/AutoMapper/AutoMapper/wiki/Queryable- एक्सटेंशन –