एक DataTable पर LINQ क्वेरी


1031

मैं एक DataTable ऑब्जेक्ट पर एक LINQ क्वेरी करने की कोशिश कर रहा हूं और विचित्र रूप से मुझे पता चल रहा है कि DataTables पर इस तरह के प्रश्नों का प्रदर्शन सीधा नहीं है। उदाहरण के लिए:

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;

इसकी अनुमति नहीं है। मैं इस काम को कैसे प्राप्त करूं?

मुझे आश्चर्य है कि DataTables पर LINQ क्वेरी की अनुमति नहीं है!


जवाबों:


1279

आप के खिलाफ क्वेरी नहीं कर सकते हैं DataTableकी पंक्तियाँ संग्रह के बाद से, DataRowCollectionको लागू नहीं करता है IEnumerable<T>। आपको AsEnumerable()एक्सटेंशन का उपयोग करने की आवश्यकता है DataTable। इस तरह:

var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;

और जैसा @Keith कहता है, आपको System.Data.DataSetExtensions का संदर्भ जोड़ना होगा

AsEnumerable()लौटता है IEnumerable<DataRow>। यदि आपको IEnumerable<DataRow>एक में बदलने की जरूरत है DataTable, तो CopyToDataTable()एक्सटेंशन का उपयोग करें।

नीचे लैम्बडा एक्सप्रेशन के साथ क्वेरी दी गई है,

var result = myDataTable
    .AsEnumerable()
    .Where(myRow => myRow.Field<int>("RowNo") == 1);

8
VB संस्करण: डिम परिणाम = myRow से myDataTable.AsEnumerable _ में myRow.Field ("RowNo") = 1 _ myRow का चयन करें
Jeff

15
मेरे पास पहले से ही उल्लिखित dll का संदर्भ था, लेकिन गायब थाusing System.Data;
ल्यूक डुड्रिज

5
वीबी संस्करण को myRow.Field और ("RowNo") के बीच (स्ट्रिंग का) सम्मिलित करने की आवश्यकता है। उस हिस्से को पढ़ना चाहिए: myRow.Field (स्ट्रिंग का) ("रोवनो") = 1 - संदर्भ @Cros टिप्पणी।
Yougotiger

8
यह समाधान अनावश्यक रूप से जटिल है। myDataTable.Rows@JoelFan के सुझाव के बजाय उपयोग करें ।
षड़यंत्र

10
@ मर्कस स्पष्ट करने के लिए, @ जोएलफैन के समाधान के साथ काम करने myDataTable.Rowsका कारण यह है कि myRowचर स्पष्ट रूप से डाला जाता है DataRow। जब इसे संकलित किया जाता है, तो उस क्वेरी को फिर से लिखा जाता है myDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)। व्यक्तिगत रूप से, मैं कॉल से AsEnumerable()अधिक जटिल किसी भी कॉल को नहीं ढूंढता Cast<DataRow>()। जहां तक ​​मुझे पता है, प्रदर्शन समान है, इसलिए यह सिर्फ वरीयता का मामला है।
Collin K

129
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow

2
केवल पंक्ति 1 के बजाय कई पंक्तियों का चयन करने के बारे में क्या?
अडजिट

2
बस "जहां" लाइन को हटा दें और आपको सभी पंक्तियां मिलेंगी
जोएलफैन

1
हां, यह है कि मैं इसका उपयोग कैसे करता हूं, (int)myRow["RowNo"]सामान्य रूप myRow.Field<int>("RowNo")से अधिक सुगमता से समर्थन करने के लिए अशक्त प्रकारों को बदलने के अलावा ।
जोनास

69

ऐसा नहीं है कि उन्हें जानबूझकर डेटाटेबल्स पर अनुमति नहीं दी गई थी, यह सिर्फ इतना है कि डेटाटेबल्स IQueryable और जेनरिक IEnumerable कंस्ट्रक्शन को प्री-डेट करते हैं, जिस पर लिनक क्वेश्चन किए जा सकते हैं।

दोनों इंटरफेस को कुछ प्रकार की सुरक्षा की आवश्यकता होती है। डेटाटेबल्स दृढ़ता से टाइप नहीं किए जाते हैं। यह वही कारण है कि लोग ArrayList के खिलाफ क्वेरी नहीं कर सकते, उदाहरण के लिए।

Linq को काम करने के लिए आपको अपने परिणामों को टाइप-सुरक्षित ऑब्जेक्ट के विरुद्ध मैप करना होगा और उसके बजाय क्वेरी करनी होगी।


49

जैसा कि @ ch00k ने कहा:

using System.Data; //needed for the extension methods to work

...

var results = 
    from myRow in myDataTable.Rows 
    where myRow.Field<int>("RowNo") == 1 
    select myRow; //select the thing you want, not the collection

आपको एक प्रोजेक्ट संदर्भ भी जोड़ना होगा System.Data.DataSetExtensions


1
यदि आप यह कोशिश करते हैं, तो आप पाएंगे कि यह तब तक काम नहीं करेगा जब तक कि आप एक विशिष्ट प्रकार का myRowउपयोग नहीं Cast<DataRow>()करते हैं Rows। उपयोग करने के लिए बेहतर है AsEnumerable()
नेटमैज

1
@NetMage ने 12 साल पहले काम किया था जब मैंने इसे पोस्ट किया था। जब तक आपके पास है System.Linqऔर System.Data.DataSetExtensionsफिर वैसे भी myDataTable.Rowsएक संग्रहणीय संग्रह देता DataRowहै। यह बदल गया है, यह एक दशक हो गया है जब से मैंने इसका इस्तेमाल किया है।
कीथ

1
दिलचस्प है - मुझे लगता है कि इसे किसी बिंदु पर बदल दिया गया था, क्योंकि यह अभी .Net या .Net कोर पर काम नहीं करता है।
नेटमैज

1
@NetMage हाँ, मुझे आश्चर्य नहीं है कि DataSetएक्सटेंशन ने इसे .NET कोर या .NET स्टैंडर्ड में नहीं बनाया, जब मैंने यह उत्तर पोस्ट किया तो वे पहले से ही आउटडेटेड थे। मैं वास्तव DataSetमें नई परियोजनाओं में उपयोग नहीं करूंगा , कोडिंग और प्रदर्शन में आसानी के लिए दोनों से कहीं बेहतर डेटा एक्सेस मॉडल हैं।
कीथ

1
वे वहाँ हैं, लेकिन सिर्फ इतना DataRowCollectionलागू नहीं करता है और दृढ़ता से टाइप किए गए LINQ के साथ काम नहीं करता है। IEnumerable<T>IEnumerable
नेटमैज

38
var query = from p in dt.AsEnumerable()
                    where p.Field<string>("code") == this.txtCat.Text
                    select new
                    {
                        name = p.Field<string>("name"),
                        age= p.Field<int>("age")                         
                    };

नाम और आयु क्षेत्र अब क्वेरी ऑब्जेक्ट का हिस्सा हैं और इसे इस तरह एक्सेस किया जा सकता है: Console.WriteLine (query.name);


मैं नाम का उपयोग कैसे करूं? उदाहरण के लिए, MessageBox.Show(name)अपरिभाषित है।

35

मुझे लगता है कि इस पर कुछ बार जवाब दिया गया है, लेकिन सिर्फ एक और दृष्टिकोण पेश करने के लिए:

मुझे .Cast<T>()विधि का उपयोग करना पसंद है , यह स्पष्ट प्रकार को परिभाषित करने और गहराई से देखने में मुझे पवित्रता बनाए रखने में मदद करता है, मुझे लगता है कि .AsEnumerable()इसे वैसे भी कहते हैं:

var results = from myRow in myDataTable.Rows.Cast<DataRow>() 
                  where myRow.Field<int>("RowNo") == 1 select myRow;

या

var results = myDataTable.Rows.Cast<DataRow>()
                      .FirstOrDefault(x => x.Field<int>("RowNo") == 1);

जैसा कि टिप्पणियों में उल्लेख किया गया है, किसी अन्य विधानसभाओं की जरूरत नहीं है क्योंकि यह Linq ( संदर्भ ) का हिस्सा है


5
यह System.Data.DataSetExtensions को संदर्भित किए बिना काम करता है।
user423430

29

DataSet / DataTable में डेटा में हेरफेर करने के लिए LINQ का उपयोग करना

var results = from myRow in tblCurrentStock.AsEnumerable()
              where myRow.Field<string>("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
              select myRow;
DataView view = results.AsDataView();

1
AsDataView मेरे लिए Intellisense में दिखाई नहीं देता है। मैंने System.Data.Linq का उपयोग करना और System.Linq का उपयोग करना शामिल किया लेकिन फिर भी यह काम नहीं कर रहा है। क्या आप जानते हैं कि मैं क्या याद कर रहा हूँ? अग्रिम में धन्यवाद।
नाओमी

@Naomi यह से आता है System.Data.DataSetExtensions
लुई वावरू

29
//Create DataTable 
DataTable dt= new DataTable();
dt.Columns.AddRange(new DataColumn[]
{
   new DataColumn("ID",typeof(System.Int32)),
   new DataColumn("Name",typeof(System.String))

});

//Fill with data

dt.Rows.Add(new Object[]{1,"Test1"});
dt.Rows.Add(new Object[]{2,"Test2"});

//Now  Query DataTable with linq
//To work with linq it should required our source implement IEnumerable interface.
//But DataTable not Implement IEnumerable interface
//So we call DataTable Extension method  i.e AsEnumerable() this will return EnumerableRowCollection<DataRow>


// Now Query DataTable to find Row whoes ID=1

DataRow drow = dt.AsEnumerable().Where(p=>p.Field<Int32>(0)==1).FirstOrDefault();
 // 

22

क्वेरी की इस सरल रेखा को आज़माएं:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);

4
मैं " क्वेरी सिंटैक्स " (स्वीकृत उत्तर में ) के ऊपर " मेथड चाइनिंग " (जैसा कि आपने यहां किया है) पसंद करता हूं, क्योंकि यह एक बुनियादी जहां-क्लॉज है जो एक लाइन पर फिट बैठता है और अभी भी बहुत पठनीय है। प्रत्येक अपने स्वयं के लिए।
माइकटेवी

16

आप पंक्तियों के संग्रह में LINQ का उपयोग वस्तुओं पर कर सकते हैं, जैसे:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;

1
क्योंकि DataTable.Rowsयह लागू नहीं होता है IEnumerable, मैं नहीं देख सकता कि यह क्वेरी कैसे संकलित हो सकती है।
onedaywhen

@onedaywhen मैंने अभी कुछ कोड में ऐसा किया है और यह संकलन करता है। अभी यह पता लगाने की कोशिश क्यों की जा रही है।
डेपरन

... या आप केवल चयन विधि के भीतर एक फ़िल्टर अभिव्यक्ति का उपयोग कर सकते हैं: var results = myDataTable.Select ("RowNo = 1"); यह एक DataRow सरणी देता है।
इशिकावा

12

यह एक सरल तरीका है जो मेरे लिए काम करता है और लैम्बडा एक्सप्रेशन का उपयोग करता है:

var results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)

फिर यदि आप एक विशेष मूल्य चाहते हैं:

if(results != null) 
    var foo = results["ColName"].ToString()


11

सबसे अधिक संभावना है, डेटासेट, डेटाटेबल और डेटारॉ के लिए कक्षाएं पहले से ही समाधान में परिभाषित की गई हैं। यदि ऐसा है तो आपको DataSetExtensions reference की आवश्यकता नहीं होगी।

पूर्व। DataSet वर्ग का नाम-> CustomSet, DataRow वर्ग का नाम-> CustomTableRow (परिभाषित स्तंभों के साथ: रोवनो, ...)

var result = from myRow in myDataTable.Rows.OfType<CustomSet.CustomTableRow>()
             where myRow.RowNo == 1
             select myRow;

या (जैसा मैं पसंद करता हूं)

var result = myDataTable.Rows.OfType<CustomSet.CustomTableRow>().Where(myRow => myRow.RowNo);


8

अपने आवेदन में मैंने पाया कि डेटाटेबल के लिए AsEnumerable () एक्सटेंशन के साथ LINQ से डेटासेट्स का उपयोग करना जैसा कि उत्तर में सुझाव दिया गया था, बहुत धीमा था। यदि आप गति के लिए अनुकूलन करने में रुचि रखते हैं, तो जेम्स न्यूटनकिंग की Json.Net लाइब्रेरी ( http://james.newtonking.com/json/help/index.html ) का उपयोग करें

// Serialize the DataTable to a json string
string serializedTable = JsonConvert.SerializeObject(myDataTable);    
Jarray dataRows = Jarray.Parse(serializedTable);

// Run the LINQ query
List<JToken> results = (from row in dataRows
                    where (int) row["ans_key"] == 42
                    select row).ToList();

// If you need the results to be in a DataTable
string jsonResults = JsonConvert.SerializeObject(results);
DataTable resultsTable = JsonConvert.DeserializeObject<DataTable>(jsonResults);

मुझे संदेह है कि यह सामान्य मामलों में तेज है। इसमें दो क्रमांकन, एक deserialization और एक पार्सिंग संचालन का ओवरहेड है। इसके बावजूद, मैंने इसे अस्वीकार कर दिया है क्योंकि यह संक्षिप्त नहीं है, अर्थात क्रमांकन / डीरियलाइज़ेशन यह स्पष्ट नहीं करता है कि इरादा किसी सूची को फ़िल्टर करने का है।
एक फु

@an phu, .AsEnumerable एक्सटेंशन विधि का उपयोग करके हैवीवेट System.Data.DataRowऑब्जेक्ट का संग्रह बनाता है । क्रमबद्ध और पार्स की गई डेटा तालिका केवल स्तंभ नामों और प्रत्येक पंक्ति के मूल्यों से युक्त हल्के डेटा को बनाती है। जब क्वेरी चलती है, तो यह डेटा को मेमोरी में लोड कर देगा, जिसमें बड़े डेटासेट के लिए स्वैपिंग शामिल हो सकती है। कभी-कभी, कई ऑपरेशनों का ओवरहेड मेमोरी में बड़ी मात्रा में डेटा की नकल करने के ओवरहेड से कम होता है।
LandGGently


7
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;

7

नीचे दिए गए इसे कैसे प्राप्त करें, इस पर उदाहरण:

DataSet dataSet = new DataSet(); //Create a dataset
dataSet = _DataEntryDataLayer.ReadResults(); //Call to the dataLayer to return the data

//LINQ query on a DataTable
var dataList = dataSet.Tables["DataTable"]
              .AsEnumerable()
              .Select(i => new
              {
                 ID = i["ID"],
                 Name = i["Name"]
               }).ToList();

6

इसे इस्तेमाल करे...

SqlCommand cmd = new SqlCommand( "Select * from Employee",con);
SqlDataReader dr = cmd.ExecuteReader( );
DataTable dt = new DataTable( "Employee" );
dt.Load( dr );
var Data = dt.AsEnumerable( );
var names = from emp in Data select emp.Field<String>( dt.Columns[1] );
foreach( var name in names )
{
    Console.WriteLine( name );
}

5

आप इसे इस तरह से linq के माध्यम से काम कर सकते हैं:

from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable()
where prod.Field<decimal>("UnitPrice") > 62.500M
select prod

या डायनामिक लाइन की तरह यह (AsDynamic को सीधे डेटासेट पर कहा जाता है):

TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M)

मैं अंतिम दृष्टिकोण पसंद करता हूं जबकि सबसे अधिक लचीला है। पुनश्च: System.Data.DataSetExtensions.dllसंदर्भ कनेक्ट करने के लिए मत भूलना


5

आप यह कोशिश कर सकते हैं, लेकिन आपको प्रत्येक कॉलम के लिए मूल्यों का प्रकार निश्चित होना चाहिए

List<MyClass> result = myDataTable.AsEnumerable().Select(x=> new MyClass(){
     Property1 = (string)x.Field<string>("ColumnName1"),
     Property2 = (int)x.Field<int>("ColumnName2"),
     Property3 = (bool)x.Field<bool>("ColumnName3"),    
});

क्या दुनिया पागल हो गयी है? Sql में क्या गलत है? DataRow [] drs = dt.Select ("id = 1"); शायद यह बहुत आसान है।
प्रोग्रामिक

0

मैं निम्नलिखित समाधान प्रस्तावित करता हूं:

DataView view = new DataView(myDataTable); 
view.RowFilter = "RowNo = 1";
DataTable results = view.ToTable(true);

DataView दस्तावेज़ीकरण को देखते हुए , पहली चीज़ जो हम देख सकते हैं वह यह है:

छांटने, छानने, खोज, संपादन और नेविगेशन के लिए डेटाटेबल के एक डेटाटेबल्ड, अनुकूलित दृश्य का प्रतिनिधित्व करता है।

इससे मुझे जो मिल रहा है, वह यह है कि DataTable केवल डेटा स्टोर करने के लिए है और DataViewable हमें Dataable के खिलाफ "क्वेरी" करने में सक्षम है।

यहाँ इस विशेष मामले में यह कैसे काम करता है:

आप SQL कथन को लागू करने का प्रयास करें

SELECT *
FROM myDataTable
WHERE RowNo = 1

"डेटाटेबल भाषा" में। C # में हम इसे इस तरह पढ़ेंगे:

FROM myDataTable
WHERE RowNo = 1
SELECT *

जो सी # में इस तरह दिखता है:

DataView view = new DataView(myDataTable);  //FROM myDataTable
view.RowFilter = "RowNo = 1";  //WHERE RowNo = 1
DataTable results = view.ToTable(true);  //SELECT *

0
                    //Json Formating code
                    //DT is DataTable
                    var filter = (from r1 in DT.AsEnumerable()

                                  //Grouping by multiple columns 
                                  group r1 by new
                                  {
                                      EMPID = r1.Field<string>("EMPID"),
                                      EMPNAME = r1.Field<string>("EMPNAME"),

                                  } into g
                                  //Selecting as new type
                                  select new
                                  {

                                      EMPID = g.Key.EMPID,
                                      MiddleName = g.Key.EMPNAME});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.