linq ट्यूटोरियल
लाइनक के साथ शुरुआत करना
खोज…
टिप्पणियों
LINQ .NET फ्रेमवर्क संस्करण 3.5 में शुरू की गई सुविधाओं का एक समूह है जो वस्तुओं की दुनिया और डेटा की दुनिया के बीच की खाई को पाटता है।
परंपरागत रूप से, डेटा के विरुद्ध प्रश्नों को सरल प्रकार के रूप में व्यक्त किया जाता है, जैसे संकलन के समय या इंटेलीसेनस समर्थन पर जाँच किए बिना। इसके अलावा, आपको प्रत्येक प्रकार के डेटा स्रोत के लिए एक अलग क्वेरी भाषा सीखनी होगी: SQL डेटाबेस, XML दस्तावेज़, विभिन्न वेब सेवाएँ, और इसी तरह। LINQ C क्वेरी को C # और Visual Basic में प्रथम श्रेणी का भाषा निर्माण बनाता है। आप भाषा कीवर्ड और परिचित संचालकों का उपयोग करके वस्तुओं के जोरदार टाइप किए गए संग्रह के खिलाफ क्वेरी लिखते हैं।
सेट अप
LINQ को .NET 3.5 या उच्चतर (या LINQBridge का उपयोग करके .NET 2.0) की आवश्यकता है।
यदि यह अभी तक जोड़ा नहीं गया है, तो System.Core में एक संदर्भ जोड़ें।
फ़ाइल के शीर्ष पर, नाम स्थान आयात करें:
- सी#
using System;
using System.Linq;
- VB.NET
Imports System.Linq
LINQ में अलग-अलग मिलती है
निम्नलिखित उदाहरणों में, हम निम्नलिखित नमूनों का उपयोग करेंगे:
List<Product> Products = new List<Product>()
{
new Product()
{
ProductId = 1,
Name = "Book nr 1",
Price = 25
},
new Product()
{
ProductId = 2,
Name = "Book nr 2",
Price = 15
},
new Product()
{
ProductId = 3,
Name = "Book nr 3",
Price = 20
},
};
List<Order> Orders = new List<Order>()
{
new Order()
{
OrderId = 1,
ProductId = 1,
},
new Order()
{
OrderId = 2,
ProductId = 1,
},
new Order()
{
OrderId = 3,
ProductId = 2,
},
new Order()
{
OrderId = 4,
ProductId = NULL,
},
};
आंतरिक रूप से जुड़ा
क्वेरी सिंटैक्स
var joined = (from p in Products
join o in Orders on p.ProductId equals o.ProductId
select new
{
o.OrderId,
p.ProductId,
p.Name
}).ToList();
विधि सिंटेक्स
var joined = Products.Join(Orders, p => p.ProductId,
o => o.OrderId,
=> new
{
OrderId = o.OrderId,
ProductId = p.ProductId,
Name = p.Name
})
.ToList();
परिणाम:
{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" }
बाईं ओर का बाहरी जोड़
var joined = (from p in Products
join o in Orders on p.ProductId equals o.ProductId into g
from lj in g.DefaultIfEmpty()
select new
{
//For the empty records in lj, OrderId would be NULL
OrderId = (int?)lj.OrderId,
p.ProductId,
p.Name
}).ToList();
परिणाम:
{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" },
{ NULL, 3, "Book nr 3" }
क्रोस जॉइन
var joined = (from p in Products
from o in Orders
select new
{
o.OrderId,
p.ProductId,
p.Name
}).ToList();
परिणाम:
{ 1, 1, "Book nr 1" },
{ 2, 1, "Book nr 1" },
{ 3, 2, "Book nr 2" },
{ NULL, 3, "Book nr 3" },
{ 4, NULL, NULL }
ग्रुप जोइन
var joined = (from p in Products
join o in Orders on p.ProductId equals o.ProductId
into t
select new
{
p.ProductId,
p.Name,
Orders = t
}).ToList();
प्रॉपरटी Orders
अब सभी लिंक किए गए ऑर्डर्स के साथ एक IEnumerable<Order>
होता है।
परिणाम:
{ 1, "Book nr 1", Orders = { 1, 2 } },
{ 2, "Book nr 2", Orders = { 3 } },
{ 3, "Book nr 3", Orders = { } },
कई शर्तों पर कैसे जुड़ें
एक ही स्थिति में शामिल होने पर, आप उपयोग कर सकते हैं:
join o in Orders
on p.ProductId equals o.ProductId
एकाधिक में शामिल होने पर, उपयोग करें:
join o in Orders
on new { p.ProductId, p.CategoryId } equals new { o.ProductId, o.CategoryId }
सुनिश्चित करें कि दोनों गुमनाम वस्तुओं एक ही गुण होते हैं, और VB.NET में, वे चिह्नित किया जाना चाहिए Key
है, हालांकि VB.NET कई अनुमति देता Equals
खंड से अलग कर दिया And
:
Join o In Orders
On p.ProductId Equals o.ProductId And p.CategoryId Equals o.CategoryId
क्वेरी सिंटैक्स और विधि सिंटैक्स
क्वेरी सिंटैक्स और विधि सिंटैक्स शब्दशः समान होते हैं, लेकिन बहुत से लोग क्वेरी सिंटैक्स को सरल और पढ़ने में आसान पाते हैं। मान लीजिए कि हमें संख्याओं के संग्रह से आरोही क्रम में आदेशित सभी वस्तुओं को पुनः प्राप्त करना है।
सी#:
int[] numbers = { 0, 1, 2, 3, 4, 5, 6 };
// Query syntax:
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
// Method syntax:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
VB.NET:
Dim numbers() As Integer = { 0, 1, 2, 3, 4, 5, 6 }
' Query syntax: '
Dim numQuery1 = From num In numbers
Where num Mod 2 = 0
Select num
Order By num
' Method syntax: '
Dim numQuery2 = numbers.where(Function(num) num Mod 2 = 0).OrderBy(Function(num) num)
याद रखें कि कुछ प्रश्नों को विधि कॉल के रूप में व्यक्त किया जाना चाहिए। उदाहरण के लिए, आपको किसी क्वेरी को व्यक्त करने के लिए एक विधि कॉल का उपयोग करना चाहिए जो निर्दिष्ट स्थिति से मेल खाने वाले तत्वों की संख्या को पुनः प्राप्त करता है। आपको किसी क्वेरी के लिए एक विधि कॉल का उपयोग करना होगा जो उस स्रोत को अधिकतम मान रखने वाले तत्व को पुनः प्राप्त करता है। ताकि कोड को अधिक सुसंगत बनाने के लिए विधि सिंटैक्स का उपयोग करने का एक फायदा हो सके। हालाँकि, निश्चित रूप से आप हमेशा क्वेरी सिंटैक्स कॉल के बाद विधि लागू कर सकते हैं:
सी#:
int maxNum =
(from num in numbers
where num % 2 == 0
select num).Max();
VB.NET:
Dim maxNum =
(From num In numbers
Where num Mod 2 = 0
Select num).Max();
LINQ विधियाँ, और IEnumerable बनाम IQueryable
IEnumerable<T>
पर LINQ एक्सटेंशन मेथड्स वास्तविक तरीके 1 , चाहे अनाम विधियाँ हों:
//C#
Func<int,bool> fn = x => x > 3;
var list = new List<int>() {1,2,3,4,5,6};
var query = list.Where(fn);
'VB.NET
Dim fn = Function(x As Integer) x > 3
Dim list = New List From {1,2,3,4,5,6};
Dim query = list.Where(fn);
या नामित विधियाँ (विधियाँ स्पष्ट रूप से एक वर्ग के भाग के रूप में परिभाषित):
//C#
class Program {
bool LessThan4(int x) {
return x < 4;
}
void Main() {
var list = new List<int>() {1,2,3,4,5,6};
var query = list.Where(LessThan4);
}
}
'VB.NET
Class Program
Function LessThan4(x As Integer) As Boolean
Return x < 4
End Function
Sub Main
Dim list = New List From {1,2,3,4,5,6};
Dim query = list.Where(AddressOf LessThan4)
End Sub
End Class
सिद्धांत रूप में, विधि के आईएल को पार्स करना संभव है, यह पता लगाने की कि विधि क्या करने की कोशिश कर रही है, और उस पद्धति के तर्क को किसी भी अंतर्निहित डेटा स्रोत पर लागू करें, न कि केवल वस्तुओं में। लेकिन आईएल पार्स करना दिल के बेहोश होने के लिए नहीं है।
सौभाग्य से, .NET इस परिदृश्य के लिए, IQueryable<T>
इंटरफ़ेस, और System.Linq.Queryable
पर विस्तार के तरीके प्रदान करता है। ये विस्तार विधियाँ एक अभिव्यक्ति ट्री लेती हैं - एक डेटा संरचना जो कोड का प्रतिनिधित्व करती है - एक वास्तविक विधि के बजाय, जिसे LINQ प्रदाता फिर 2 पार्स कर सकता है और अंतर्निहित डेटा स्रोत को क्वेरी करने के लिए अधिक उपयुक्त रूप में परिवर्तित कर सकता है। उदाहरण के लिए:
//C#
IQueryable<Person> qry = PersonsSet();
// Since we're using a variable of type Expression<Func<Person,bool>>, the compiler
// generates an expression tree representing this code
Expression<Func<Person,bool>> expr = x => x.LastName.StartsWith("A");
// The same thing happens when we write the lambda expression directly in the call to
// Queryable.Where
qry = qry.Where(expr);
'VB.NET
Dim qry As IQueryable(Of Person) = PersonSet()
' Since we're using a variable of type Expression(Of Func(Of Person,Boolean)), the compiler
' generates an expression tree representing this code
Dim expr As Expression(Of Func(Of Person, Boolean)) = Function(x) x.LastName.StartsWith("A")
' The same thing happens when we write the lambda expression directly in the call to
' Queryable.Where
qry = qry.Where(expr)
यदि (उदाहरण के लिए) यह क्वेरी SQL डेटाबेस के विरुद्ध है, तो प्रदाता इस अभिव्यक्ति को निम्न SQL कथन में बदल सकता है:
SELECT *
FROM Persons
WHERE LastName LIKE N'A%'
और इसे डेटा स्रोत के विरुद्ध निष्पादित करें।
दूसरी ओर, यदि क्वेरी REST API के विरुद्ध है, तो प्रदाता उसी अभिव्यक्ति को API कॉल में बदल सकता है:
http://www.example.com/person?filtervalue=A&filtertype=startswith&fieldname=lastname
एक अभिव्यक्ति के आधार पर एक डेटा अनुरोध को सिलाई करने में दो प्राथमिक लाभ हैं (पूरे संग्रह को मेमोरी में लोड करने और स्थानीय रूप से क्वेरी करने के विरोध में):
- अंतर्निहित डेटा स्रोत अक्सर अधिक कुशलता से क्वेरी कर सकता है। उदाहरण के लिए,
LastName
पर एक इंडेक्स बहुत अच्छी तरह से हो सकता है। स्थानीय मेमोरी में ऑब्जेक्ट लोड करना और इन-मेमोरी को क्वेरी करना उस दक्षता को खो देता है। - हस्तांतरित होने से पहले डेटा को आकार और कम किया जा सकता है। इस मामले में, डेटाबेस / वेब सेवा को केवल डेटा मिलान करने की आवश्यकता है, क्योंकि डेटा स्रोत से उपलब्ध व्यक्तियों के पूरे सेट के विपरीत।
टिप्पणियाँ
1. तकनीकी रूप से, वे वास्तव में विधियाँ नहीं लेते हैं, बल्कि ऐसे उदाहरण प्रस्तुत करते हैं जो विधियों की ओर संकेत करते हैं । हालाँकि, यह अंतर यहाँ अप्रासंगिक है।
2. यह त्रुटियों के लिए कारण है जैसे " LINQ to Entities विधि '' System.String ToString () 'विधि को नहीं पहचानता है, और इस पद्धति को स्टोर अभिव्यक्ति में अनुवादित नहीं किया जा सकता है। " LINQ प्रदाता (इस मामले में एंटिटी फ्रेमवर्क प्रदाता) को पता नहीं है कि किसी कॉल को ToString
से SQL के बराबर कैसे करें।