c# - استعلام LINQ على DataTable




11 Answers

لا يمكنك الاستعلام عن مجموعة صفوف DataTable ، حيث أن DataRowCollection لا يقوم بتطبيق IEnumerable<T> . تحتاج إلى استخدام ملحق AsEnumerable() لـ DataTable . مثل ذلك:

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

وكما يقول كيث ، ستحتاج إلى إضافة مرجع إلى System.Data.DataSetExtensions

إرجاع AsEnumerable() IEnumerable<DataRow> . إذا كنت بحاجة إلى تحويل IEnumerable<DataRow> إلى DataTable ، استخدم CopyToDataTable() .

أحاول تنفيذ استعلام LINQ على كائن DataTable وغريبًا أجد أن تنفيذ مثل هذه الاستعلامات على DataTables ليس واضحًا. فمثلا:

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

هذا غير مسموح به. كيف يمكنني الحصول على شيء مثل هذا العمل؟

أنا مندهش من أن استعلامات LINQ غير مسموح بها على DataTables!




لا يعني ذلك أنه لم يتم السماح لهم عمداً على DataTables ، بل إن DataTables هي فقط التي تسبق تاريخ التركيبات IEnumerable IQueryable والعامة التي يمكن إجراء استعلامات Linq عليها.

تتطلب كل الواجهات بعض التحقق من سلامة نوع الفرز. لا تتم كتابة DataTables بشكل كبير. هذا هو نفس السبب في عدم تمكن الأشخاص من الاستعلام عن ArrayList ، على سبيل المثال.

لكي تعمل Linq تحتاج إلى تعيين نتائجك مقابل كائنات آمنة من النوع والاستعلام عن ذلك بدلاً من ذلك.




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



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



يمكنك استخدام LINQ للكائنات الموجودة في مجموعة الصفوف ، مثل:

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



جرب هذا

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



هذه طريقة بسيطة تعمل من أجلي وتستخدم تعبيرات لامدا:

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

ثم إذا كنت تريد قيمة معينة:

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



بالنسبة إلى VB.NET ، سيبدو الرمز كما يلي:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow



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



يمكنك الحصول على العمل الأنيق عبر linq مثل هذا:

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

أو مثل linq ديناميكي هذا (يتم استدعاء AsDynamic مباشرة على DataSet):

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

أنا أفضل النهج الأخير بينما هو الأكثر مرونة. PS: لا تنس ربط مرجع System.Data.DataSetExtensions.dll




يمكنك تجربة ذلك ، ولكن يجب التأكد من نوع القيم لكل عمود

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



Related

c# .net linq datatable .net-3.5