c# - डेटाटेबल पर LINQ क्वेरी




.net datatable .net-3.5 (18)

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

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

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

मुझे आश्चर्य है कि डेटाटेबल्स पर LINQ क्वेरीज़ की अनुमति नहीं है!


Answers

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

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 );
}

मेरे आवेदन में मैंने पाया कि उत्तर में सुझाए गए डेटाटेबल के लिए AsNnumerable () एक्सटेंशन के साथ LINQ से डेटासेट का उपयोग करना बेहद धीमा था। यदि आप गति के लिए अनुकूलित करने में रुचि रखते हैं, तो जेम्स न्यूटनकिंग की जेसननेट लाइब्रेरी का उपयोग करें ( 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);

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

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

//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();
 // 

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

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 

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

पूर्व। डेटासेट क्लास नाम-> कस्टमसेट, डेटारो क्लास नाम-> कस्टमटेबलरो (परिभाषित कॉलम के साथ: रोनो, ...)

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);

जैसा कि @ 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 एक प्रोजेक्ट संदर्भ जोड़ने की भी आवश्यकता है


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

आप लाइन संग्रह पर ऑब्जेक्ट्स के लिए LINQ का उपयोग कर सकते हैं, जैसे:

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

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

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

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

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

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


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

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

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

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


मुझे एहसास है कि इसका उत्तर कुछ बार दिया गया है, लेकिन सिर्फ एक और दृष्टिकोण प्रदान करने के लिए, मुझे .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 के माध्यम से सुरुचिपूर्ण काम कर सकते हैं:

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

या गतिशील linq की तरह (AsDynamic सीधे डेटासेट पर कहा जाता है):

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

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


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

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

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

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

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")                         
                    };

मैंने कुछ एक्सटेंशन विधियां (नीचे) बनाई हैं, इसलिए यदि आपको IQueryable पहले ही आदेश दिया गया है या नहीं, तो आपको चिंता करने की ज़रूरत नहीं है। यदि आप एकाधिक गुणों द्वारा ऑर्डर करना चाहते हैं तो बस इसे निम्नानुसार करें:

// We do not have to care if the queryable is already sorted or not. 
// The order of the Smart* calls defines the order priority
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);

यह विशेष रूप से सहायक होता है यदि आप ऑर्डरिंग गतिशील रूप से बनाते हैं, गुणों की सूची से क्रमबद्ध करने के लिए fe।

public static class IQueryableExtension
{
    public static bool IsOrdered<T>(this IQueryable<T> queryable) {
        if(queryable == null) {
            throw new ArgumentNullException("queryable");
        }

        return queryable.Expression.Type == typeof(IOrderedQueryable<T>);
    }

    public static IQueryable<T> SmartOrderBy<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable<T> SmartOrderByDescending<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}




c# .net linq datatable .net-3.5