के साथ IQueryable का उपयोग LINQ के संदर्भ में IQueryable
का उपयोग क्या है?LINQ
क्या यह विस्तार विधियों या किसी अन्य उद्देश्य के विकास के लिए उपयोग किया जाता है?
के साथ IQueryable का उपयोग LINQ के संदर्भ में IQueryable
का उपयोग क्या है?LINQ
क्या यह विस्तार विधियों या किसी अन्य उद्देश्य के विकास के लिए उपयोग किया जाता है?
Marc Gravell's answer बहुत पूरा हो गया है, लेकिन मैंने सोचा कि मैं देखने के उपयोगकर्ता के बिंदु से इस बारे में कुछ जोड़ना चाहते हैं, साथ ही ...
मुख्य अंतर यह है एक उपयोगकर्ता के नजरिए से, कि है, जब आप IQueryable<T>
(एक प्रदाता के साथ जो सही तरीके से समर्थन करता है) का उपयोग करते हैं, तो आप बहुत सारे संसाधनों को बचा सकते हैं।
उदाहरण के लिए, यदि आप कई ओआरएम सिस्टम के साथ रिमोट डेटाबेस के खिलाफ काम कर रहे हैं, तो आपके पास एक टेबल से डेटा को दो तरीकों से लाने का विकल्प है, जो IEnumerable<T>
देता है, और एक जो IQueryable<T>
देता है। कहें, उदाहरण के लिए, आपके पास एक उत्पाद तालिका है, और आप उन सभी उत्पादों को प्राप्त करना चाहते हैं जिनकी लागत> $ 25 है।
यदि आप कार्य करें:
IEnumerable<Product> products = myORM.GetProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
यहाँ क्या होता है, डेटाबेस लोड उत्पादों के सभी है, और अपने कार्यक्रम के लिए तार पर इन लोगों के पास करता है। आपका प्रोग्राम तब डेटा फ़िल्टर करता है। संक्षेप में, डेटाबेस SELECT * FROM Products
करता है, और आपके लिए प्रत्येक उत्पाद देता है।
सही IQueryable<T>
प्रदाता के साथ, दूसरे हाथ पर, आप कर सकते हैं:
IQueryable<Product> products = myORM.GetQueryableProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
कोड एक ही है, लेकिन अंतर यह है कि एसक्यूएल निष्पादित SELECT * FROM Products WHERE Cost >= 25
हो जाएगा।
डेवलपर के रूप में आपके पीओवी से, यह वही दिखता है। हालांकि, एक प्रदर्शन के दृष्टिकोण से, आप केवल 2 रिकॉर्ड 20,000 के बजाय नेटवर्क भर में वापस आ सकते हैं ....
संक्षेप में अपना काम बहुत IEnumerable<T>
के समान है - एक queryable डेटा स्रोत का प्रतिनिधित्व करने के लिए - अंतर किया जा रहा है कि विभिन्न LINQ विधियों (Queryable
पर) और अधिक विशिष्ट हो सकता है, प्रतिनिधियों के बजाय Expression
पेड़ का उपयोग कर क्वेरी बनाने के लिए (जो क्या Enumerable
उपयोग करता है)।
अभिव्यक्ति पेड़ों का आपके चुने हुए LINQ प्रदाता द्वारा निरीक्षण किया जा सकता है और वास्तविक क्वेरी में बदल गया - हालांकि यह स्वयं में एक काला कला है। उपयोगकर्ता लेकिन वास्तविकता में आप शायद ही कभी इस बारे में परवाह करने की जरूरत एक के रूप में -
यह वास्तव में ElementType
, Expression
और Provider
करने के लिए नीचे है। केवल एक LINQ कार्यान्वयन को गोर विवरणों को जानने की आवश्यकता है।
पुन: टिप्पणियां; मुझे यकीन नहीं है कि आप उदाहरण के जरिए क्या चाहते हैं, लेकिन LINQ-to-SQL पर विचार करें; यहां केंद्रीय वस्तु DataContext
है, जो हमारे डेटाबेस-रैपर का प्रतिनिधित्व करती है। इसमें आम तौर पर प्रति तालिका एक संपत्ति होती है (उदाहरण के लिए, Customers
), और एक तालिका IQueryable<Customer>
लागू करती है। लेकिन हम इसका अधिक उपयोग नहीं करते हैं; पर विचार करें:
using(var ctx = new MyDataContext()) {
var qry = from cust in ctx.Customers
where cust.Region == "North"
select new { cust.Id, cust.Name };
foreach(var row in qry) {
Console.WriteLine("{0}: {1}", row.Id, row.Name);
}
}
इस (सी # संकलक द्वारा) हो जाता है:
var qry = ctx.Customers.Where(cust => cust.Region == "North")
.Select(cust => new { cust.Id, cust.Name });
जो फिर से (सी # संकलक द्वारा) के रूप में व्याख्या की है:
var qry = Queryable.Select(
Queryable.Where(
ctx.Customers,
cust => cust.Region == "North"),
cust => new { cust.Id, cust.Name });
महत्वपूर्ण बात, स्थिर तरीकों पर Queryable
अभिव्यक्ति पेड़ लें, जो नियमित आईएल की बजाय, किसी ऑब्जेक्ट मॉडल में संकलित हो जाएं। उदाहरण के लिए - बस "कहां" को देखते हुए, यह हमें कुछ तुलनीय बनाता है:
var cust = Expression.Parameter(typeof(Customer), "cust");
var lambda = Expression.Lambda<Func<Customer,bool>>(
Expression.Equal(
Expression.Property(cust, "Region"),
Expression.Constant("North")
), cust);
... Queryable.Where(ctx.Customers, lambda) ...
क्या संकलक हमारे लिए बहुत कुछ नहीं करता था? यह ऑब्जेक्ट मॉडल फाड़ जा सकता है, इसका क्या मतलब के लिए निरीक्षण किया, और वापस एक साथ फिर से TSQL जनरेटर द्वारा डाल - तरह कुछ दे रही है:
SELECT c.Id, c.Name
FROM [dbo].[Customer] c
WHERE c.Region = 'North'
(स्ट्रिंग एक पैरामीटर के रूप अंत हो सकता है, मैं याद नहीं कर सकते)
यदि हम अभी एक प्रतिनिधि का उपयोग करते हैं तो इनमें से कोई भी संभव नहीं होगा। और यहQueryable
/IQueryable<T>
का बिंदु है: यह अभिव्यक्ति पेड़ का उपयोग करने के लिए प्रवेश बिंदु प्रदान करता है।
यह सब बहुत जटिल है, इसलिए यह एक अच्छा काम है कि संकलक हमारे लिए यह अच्छा और आसान बनाता है।
अधिक जानकारी के लिए, "C# in Depth" या "LINQ in Action" देखें, जिनमें से दोनों इन विषयों का कवरेज प्रदान करते हैं।
यदि आपको कोई फर्क नहीं पड़ता है तो क्या आप मुझे सरल समझने योग्य उदाहरण के साथ अपडेट कर सकते हैं (यदि आपके पास समय है)। – user190560
क्या आप समझ सकते हैं "GetQueryableProducts() की परिभाषा कहां है? "?" श्री रीड कोपेसी उत्तर में – Pankaj
एक क्वेरी में अभिव्यक्तियों का अनुवाद करने की रेखा का आनंद लिया गया है "खुद में काली कला" ... – afreeland
यह आगे लाइन के आगे पूछताछ के लिए अनुमति देता है।यदि यह सेवा सीमा से परे था, तो इस IQueryable ऑब्जेक्ट के उपयोगकर्ता को इसके साथ और अधिक करने की अनुमति होगी।
उदाहरण के लिए यदि आप निबर्ननेट के साथ आलसी लोडिंग का उपयोग कर रहे थे तो परिणामस्वरूप ग्राफ को लोड होने पर लोड किया जा सकता है।
और Marc Gravell पहले से ही IQueryable(and also IEnumerable)
के बारे में पर्याप्त वर्णित है, हालांकि मैं एक small example on IQueryable and IEnumerable
के रूप में उपलब्ध कराने के द्वारा यहां छोटे से अधिक जोड़ना चाहते हैं कई उपयोगकर्ताओं को इसके बारे में
उदाहरण पूछा: मैं डेटाबेस में दो टेबल बनाया है
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Gender] [nchar](1) NOT NULL)
CREATE TABLE [dbo].[Person]([PersonId] [int] NOT NULL PRIMARY KEY,[FirstName] [nvarchar](50) NOT NULL,[LastName] [nvarchar](50) NOT NULL)
तालिका Employee
की Primary key(PersonId)
भीहै तालिका Person
अगला कीमैं अपने आवेदन में ado.net इकाई मॉडल जोड़ा गया है और कि
public class SomeServiceClass
{
public IQueryable<Employee> GetEmployeeAndPersonDetailIQueryable(IEnumerable<int> employeesToCollect)
{
DemoIQueryableEntities db = new DemoIQueryableEntities();
var allDetails = from Employee e in db.Employees
join Person p in db.People on e.PersonId equals p.PersonId
where employeesToCollect.Contains(e.PersonId)
select e;
return allDetails;
}
public IEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerable(IEnumerable<int> employeesToCollect)
{
DemoIQueryableEntities db = new DemoIQueryableEntities();
var allDetails = from Employee e in db.Employees
join Person p in db.People on e.PersonId equals p.PersonId
where employeesToCollect.Contains(e.PersonId)
select e;
return allDetails;
}
}
वे एक ही LINQ शामिल पर सेवा वर्ग नीचे पैदा करते हैं।यह program.cs
में कहा जाता है के रूप में नीचे
class Program
{
static void Main(string[] args)
{
SomeServiceClass s= new SomeServiceClass();
var employeesToCollect= new []{0,1,2,3};
//IQueryable execution part
var IQueryableList = s.GetEmployeeAndPersonDetailIQueryable(employeesToCollect).Where(i => i.Gender=="M");
foreach (var emp in IQueryableList)
{
System.Console.WriteLine("ID:{0}, EName:{1},Gender:{2}", emp.PersonId, emp.Person.FirstName, emp.Gender);
}
System.Console.WriteLine("IQueryable contain {0} row in result set", IQueryableList.Count());
//IEnumerable execution part
var IEnumerableList = s.GetEmployeeAndPersonDetailIEnumerable(employeesToCollect).Where(i => i.Gender == "M");
foreach (var emp in IEnumerableList)
{
System.Console.WriteLine("ID:{0}, EName:{1},Gender:{2}", emp.PersonId, emp.Person.FirstName, emp.Gender);
}
System.Console.WriteLine("IEnumerable contain {0} row in result set", IEnumerableList.Count());
Console.ReadKey();
}
}
output is same for both
जाहिर
ID:1, EName:Ken,Gender:M
ID:3, EName:Roberto,Gender:M
IQueryable contain 2 row in result set
ID:1, EName:Ken,Gender:M
ID:3, EName:Roberto,Gender:M
IEnumerable contain 2 row in result set
तो सवाल क्या/जहां अंतर है परिभाषित? ऐसा लगता है कि कोई फर्क नहीं पड़ता है? वास्तव में!!
के इन अवधि
IQueryable execution part
--IQueryableQuery1
SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE ([Extent1].[PersonId] IN (0,1,2,3)) AND (N'M' = [Extent1].[Gender])
--IQueryableQuery2
SELECT
[GroupBy1].[A1] AS [C1]
FROM (SELECT
COUNT(1) AS [A1]
FROM [dbo].[Employee] AS [Extent1]
WHERE ([Extent1].[PersonId] IN (0,1,2,3)) AND (N'M' = [Extent1].[Gender])
) AS [GroupBy1]
IEnumerable execution part
--IEnumerableQuery1
SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE [Extent1].[PersonId] IN (0,1,2,3)
--IEnumerableQuery2
SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Gender] AS [Gender]
FROM [dbo].[Employee] AS [Extent1]
WHERE [Extent1].[PersonId] IN (0,1,2,3)
के दौरान उत्पन्न और इकाई framwork 5 द्वारा निष्पादित एसक्यूएल प्रश्नों पर एक नजर है
Common script for both execution part
/* these two query will execute for both IQueryable or IEnumerable to get details from Person table
Ignore these two queries here because it has nothing to do with IQueryable vs IEnumerable
--ICommonQuery1
exec sp_executesql N'SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Person] AS [Extent1]
WHERE [Extent1].[PersonId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
--ICommonQuery2
exec sp_executesql N'SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM [dbo].[Person] AS [Extent1]
WHERE [Extent1].[PersonId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=3
*/
तो तुम कुछ सवाल अब है, मुझे उन लगता है और उन्हें जवाब देने के लिए
कुछ पता लगाना करने देता है की कोशिश यहां अंक,
सभी प्रश्नों एक आम हिस्सा
WHERE [Extent1].[PersonId] IN (0,1,2,3)
क्यों है? दोनों समारोह में बुला जबकि क्योंकि दोनों समारोह IQueryable<Employee> GetEmployeeAndPersonDetailIQueryable
और SomeServiceClass
की IEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerable
एक common line in linq queries
where employeesToCollect.Contains(e.PersonId)
से क्यों AND (N'M' = [Extent1].[Gender])
हिस्सा IEnumerable execution part
में याद आ रही है, जिसका हम program.cs
में
Where(i => i.Gender == "M")
इस्तेमाल किया अब हम कर रहे हैं उस बिंदु पर जहांIQueryable
और के बीच अंतर आया जब एकIQueryable
विधि कहा जाता है, यहlinq statement written inside the method
tooks और लाने औरconstructs more appropriate sql query to execute
करने की जरूरत है पता लगाने के लिए अगरmore linq/expression is defind on the resultset
, यह सब LINQ प्रश्नों परिणाम जब तक परिभाषित इकट्ठा कोशिश
क्या entity framwork
करता है।
ऐसा लगता है कि लाभ के एक बहुत,
को कम मिलता है केवल two rows after IQueryable execution
आवेदन लेकिनके लिए लौट आएक्यों?
IEnumerable
विधि के मामले में, entity framework
विधि के अंदर लिखित लिखित कथन ले लिया और परिणाम प्राप्त करने के दौरान एसक्यूएल क्वेरी तैयार करता है। it does not include rest linq part to constructs the sql query
। यहां कॉलम gender
पर एसक्यूएल सर्वर में कोई फ़िल्टरिंग नहीं की गई है।
लेकिन आउटपुट समान हैं? चूंकि 'sql server
SO, किसी को चुनने के लिए परिणाम प्राप्त करने के बाद' एननेमेरेबल परिणाम को परिणाम स्तर पर आगे बढ़ाता है। मैं व्यक्तिगत रूप से IQueryable<T>
के रूप में फ़ंक्शन परिणाम को परिभाषित करना पसंद करता हूं क्योंकि 'IEnumerable' पर बहुत सारे लाभ हैं, तो आप join two or more IQueryable function
कर सकते हैं जो SQL सर्वर पर अधिक विशिष्ट स्क्रिप्ट उत्पन्न करता है।
उदाहरण में आप IQueryable Query(IQueryableQuery2)
IEnumerable query(IEnumerableQuery2)
से अधिक विशिष्ट स्क्रिप्ट उत्पन्न कर सकते हैं जो my point of view
में अधिक स्वीकार्य है।
पर बहुत सच्चाई "GetQueryableProducts();" की परिभाषा कहां है? – Pankaj
@StackOverflowUser यह किसी भी विधि का इरादा है जो 'IQueryable' देता है - आपके ORM या रिपॉजिटरी आदि के लिए विशिष्ट होगा –
दाएं। लेकिन आपने बताया कि इस फ़ंक्शन कॉल के बाद खंड कहां है। तो सिस्टम अभी भी फ़िल्टर से अनजान है। मेरा मतलब है कि यह अभी भी उत्पादों के सभी रिकॉर्ड लाता है। सही? – Pankaj