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




.net .net-3.5 (18)

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

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

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

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


Answers

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

أدرك أن هذا قد تم الرد عليه عدة مرات ، ولكن فقط لتقديم نهج آخر ، أحب استخدام طريقة .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);

مثال على كيفية تحقيق ذلك المقدم أدناه:

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

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

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

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


على الأرجح ، يتم تعريف فئات DataSet و DataTable و DataRow بالفعل في الحل. إذا كان هذا هو الحال ، لن تحتاج إلى مرجع DataSetExtensions.

السابق. اسم فئة DataSet-> CustomSet ، اسم فئة DataRow-> CustomTableRow (مع الأعمدة المعرفة: RowNo ، ...)

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

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

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

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

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

جرب هذا

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

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

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

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


يمكنك الحصول على العمل الأنيق عبر 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


كما قال @ 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


//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 results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;

لا يمكنك الاستعلام عن مجموعة صفوف 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() .


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





c# .net linq datatable .net-3.5