LINQ से एंटिटीज विधि 'System.String फॉर्मेट (System.String, System.Object, System.Otject') को नहीं पहचानता है


88

मेरे पास यह linq क्वेरी है:

private void GetReceivedInvoiceTasks(User user, List<Task> tasks)
{
    var areaIds = user.Areas.Select(x => x.AreaId).ToArray();

    var taskList = from i in _db.Invoices
                   join a in _db.Areas on i.AreaId equals a.AreaId
                   where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
                   select new Task {
                       LinkText = string.Format(Invoice {0} has been received from {1}, i.InvoiceNumber, i.Organisation.Name),
                       Link = Views.Edit
                   };
}

यह हालांकि मुद्दों है। मैं कार्य बनाने की कोशिश कर रहा हूं। प्रत्येक नए कार्य के लिए जब मैं लिंक टेक्स्ट को "हैलो" जैसे निरंतर स्ट्रिंग पर सेट करता हूं तो यह ठीक है। हालाँकि, ऊपर मैं इनवॉइस के गुणों का उपयोग करके संपत्ति लिंकटेक्स्ट बनाने की कोशिश कर रहा हूँ।

मुझे यह त्रुटि मिली:

आधार {System.SystemException} = {"LINQ से एंटिटीज विधि को नहीं पहचानता है। }

किसी को पता है क्यों? किसी को भी यह काम करने का एक वैकल्पिक तरीका पता है?


हां, वह मूल रूप से याद किया
AnonyMouse

जवाबों:


148

इकाई फ्रेमवर्क SQL पक्ष पर आपके प्रक्षेपण को निष्पादित करने की कोशिश कर रहा है, जहां कोई समकक्ष नहीं है string.FormatAsEnumerable()Linq के साथ उस भाग के मूल्यांकन को वस्तुओं के लिए मजबूर करने के लिए उपयोग करें ।

आपके द्वारा दिए गए पिछले उत्तर के आधार पर, मैं आपकी क्वेरी को इस तरह पुनर्गठन करूंगा:

int statusReceived = (int)InvoiceStatuses.Received;
var areaIds = user.Areas.Select(x=> x.AreaId).ToArray();

var taskList = (from i in _db.Invoices
               where i.Status == statusReceived && areaIds.Contains(i.AreaId)
               select i)
               .AsEnumerable()
               .Select( x => new Task()
               {
                  LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.Organisation.Name),
                  Link = Views.Edit
                });

इसके अलावा, मैं देख रहा हूँ कि आप क्वेरी में संबंधित संस्थाओं का उपयोग करते हैं ( Organisation.Name) सुनिश्चित करें कि आप Includeअपनी क्वेरी में उचित जोड़ते हैं , या विशेष रूप से उन गुणों को बाद में उपयोग करने के लिए, अर्थात:

var taskList = (from i in _db.Invoices
               where i.Status == statusReceived && areaIds.Contains(i.AreaId)
               select new { i.InvoiceNumber, OrganisationName = i.Organisation.Name})
               .AsEnumerable()
               .Select( x => new Task()
               {
                  LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.OrganisationName),
                  Link = Views.Edit
                });

इस तथ्य के अलावा कि चयन-नया-कार्य भाग अभिव्यक्ति ट्री अनुवाद के कारण सर्वर साइड नहीं हो सकता है, यह भी ध्यान दिया जाना चाहिए कि ऐसा करना अवांछनीय है। संभवतः, आप चाहते हैं कि कार्यों को ग्राहक पक्ष बनाया जाए। इसलिए क्वेरी का पृथक्करण और कार्यों का निर्माण और भी स्पष्ट हो सकता है।
टरमोड

3
मैं एक गुमनाम प्रकार का चयन करने की भी सिफारिश करूंगा जिसमें बस आवश्यक इनवॉइसनंबर और ऑर्गनाइजेशन हो। इसमें कोई नाम नहीं। यदि चालान इकाई बड़ी है, तो बाद के असेंबल के साथ चयन करें मैं हर कॉलम को वापस खींच लूंगा, भले ही आप केवल दो का उपयोग कर रहे हों।
डेविन

1
@ ड्विन: हाँ, मैं सहमत हूँ - वास्तव में यह वही है जो दूसरी क्वेरी का उदाहरण है।
ब्रोकनग्लास

15

IQueryableव्युत्पन्न IEnumerable, मुख्य समानता यह है कि जब आप अपनी क्वेरी बनाते हैं तो इसे डेटाबेस इंजन में उसी भाषा में पोस्ट किया जाता है, जहां आप सर्वर पर डेटा को हैंडल करने के लिए C # बताते हैं (क्लाइंट साइड नहीं) या SQL को हैंडल करने के लिए बताने के लिए। डेटा।

तो मूल रूप से जब आप कहते हैं IEnumerable.ToString(), C # डेटा संग्रह प्राप्त करता है और ToString()ऑब्जेक्ट पर कॉल करता है। लेकिन जब आप कहते हैं कि IQueryable.ToString()C # SQL को ToString()ऑब्जेक्ट पर कॉल करने के लिए कहता है लेकिन SQL में ऐसा कोई तरीका नहीं है।

दोष यह है कि जब आप सी # में डेटा को संभालते हैं, तो आप जिस संपूर्ण संग्रह को देख रहे हैं, उसे फ़िल्टर लागू करने से पहले मेमोरी में बनाया जाना चाहिए।

इसे करने का सबसे कारगर तरीका है IQueryableकि आप उन सभी फ़िल्टर के साथ क्वेरी करें , जिन्हें आप लागू कर सकते हैं।

और फिर इसे मेमोरी में बनाएँ और C # में डेटा फॉर्मेटिंग करें।

IQueryable<Customer> dataQuery = Customers.Where(c => c.ID < 100 && c.ZIP == 12345 && c.Name == "John Doe");

 var inMemCollection = dataQuery.AsEnumerable().Select(c => new
                                                  {
                                                     c.ID
                                                     c.Name,
                                                     c.ZIP,
                                                     c.DateRegisterred.ToString("dd,MMM,yyyy")
                                                   });

3

जबकि एसक्यूएल को नहीं पता है कि इसके साथ क्या करना है string.Formatयह स्ट्रिंग कॉन्फैनेटेशन कर सकता है।

यदि आप निम्नलिखित कोड चलाते हैं तो आपको वह डेटा प्राप्त करना चाहिए जो आप बाद में हैं।

var taskList = from i in _db.Invoices
               join a in _db.Areas on i.AreaId equals a.AreaId
               where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
               select new Task {
                   LinkText = "Invoice " + i.InvoiceNumber + "has been received from " + i.Organisation.Name),
                   Link = Views.Edit
               };

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


2
सुनिश्चित नहीं है कि क्यों Linq FORMATMESSAGE फ़ंक्शन docs.microsoft.com/en-us/sql/t-sql/functions/… का उपयोग करने के लिए अनुकूलित नहीं किया जा सकता है, तब तक आपका समाधान है (
भौतिकता के लिए

2
डेटाबेस संरचना और संबंधित स्तंभों की संख्या के आधार पर, इस पद्धति का AsEnumerable()उपयोग करना काफी अधिक कुशल हो सकता है। बचें AsEnumerable()और ToList()जब तक आप वास्तव में स्मृति में सभी परिणाम नहीं लाना चाहते।
क्रिस शॉलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.