LINQ query on a DataTable

Próbuję wykonać zapytanie LINQ na obiekcie DataTable i o dziwo stwierdzam, że wykonywanie takich zapytań na DataTables nie jest proste. Na przykład:

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
To nie jest dozwolone. Jak sprawić, by coś takiego działało?

Jestem zdumiony, że zapytania LINQ nie są dozwolone na DataTables!

Author: Peter Mortensen, 2008-08-14

21 answers

Nie można odpytywać kolekcji DataTable wierszy , ponieważ DataRowCollection nie implementuje IEnumerable<T>. Musisz użyć rozszerzenia AsEnumerable() dla DataTable. Tak:

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

I jak mówi Keith, musisz dodać odniesienie do systemu.Data.DataSetExtensions

AsEnumerable() zwraca IEnumerable<DataRow>. Jeśli chcesz przekonwertować IEnumerable<DataRow> na DataTable, użyj rozszerzenia CopyToDataTable().

 1141
Author: Collin K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-02 16:45:09
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow
 115
Author: JoelFan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-05 02:53:10

Nie chodzi o to, że celowo nie były dozwolone na DataTables, tylko o to, że DataTables wstępnie datuje konstrukcje IQueryable i generic IEnumerable, na których można wykonywać zapytania Linq.

Oba interfejsy wymagają pewnego rodzaju walidacji bezpieczeństwa typu sort. Bazy danych nie są mocno wpisywane. Jest to ten sam powód, dla którego ludzie nie mogą odpytywać na przykład przeciwko ArrayList.

Aby Linq zadziałało, musisz mapować swoje wyniki na podstawie obiektów bezpiecznych dla typu i wyszukiwać na podstawie tego zamiast tego.

 58
Author: Jon Limjap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-14 10:10:55

Jak powiedział @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

Musisz również dodać odniesienie do projektu do System.Data.DataSetExtensions

 46
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-14 11:07:52
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")                         
                    };
 35
Author: Ravi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-08 22:23:46

Używanie LINQ do manipulowania danymi w DataSet / DataTable

var results = from myRow in tblCurrentStock.AsEnumerable()
              where myRow.Field<string>("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
              select myRow;
DataView view = results.AsDataView();
 25
Author: Salim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 04:10:38
//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();
 // 
 24
Author: sushil pandey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-04 22:08:01

Zdaję sobie sprawę, że odpowiedź na to pytanie została udzielona kilka razy, ale aby zaoferować inne podejście, lubię używać metody .Cast<T>(), która pomaga mi zachować zdrowy rozsądek w widzeniu zdefiniowanego typu explicit i w głębi duszy myślę, że .AsEnumerable() nazywa ją tak czy inaczej: {]}

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

Lub

var results = myDataTable.Rows.Cast<DataRow>()
                  .FirstOrDefault(x => x.Field<int>("RowNo") == 1);
 20
Author: vandsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 02:07:52

Możesz używać LINQ do obiektów w kolekcji Rows, w ten sposób:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
 13
Author: David Wengier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-14 10:11:08

Spróbuj tego prostego wiersza zapytania:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
 13
Author: Mohit Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 12:15:34

Spróbuj tego

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 
 9
Author: midhun sankar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-18 07:51:09

Jest to prosty sposób, który działa dla mnie i używa wyrażeń lambda:

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

Wtedy jeśli chcesz mieć określoną wartość:

if(results != null) 
    var foo = results["ColName"].ToString()
 8
Author: Matt Kemp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-18 22:13:55

Najprawdopodobniej klasy dla DataSet, DataTable i DataRow są już zdefiniowane w rozwiązaniu. W takim przypadku nie będziesz potrzebował referencji DataSetExtensions.

Ex. DataSet class name - > CustomSet, DataRow class name - > CustomTableRow (z zdefiniowanymi kolumnami: RowNo,...)

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

Lub (jak wolę)

var result = myDataTable.Rows.OfType<CustomSet.CustomTableRow>().Where(myRow => myRow.RowNo);
 8
Author: xadriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 12:16:07
var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
 7
Author: Vinay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-01 12:16:51

W mojej aplikacji odkryłem, że używanie LINQ do zbiorów danych z rozszerzeniem AsEnumerable() dla DataTable, jak sugerowano w odpowiedzi, było bardzo powolne. Jeśli jesteś zainteresowany optymalizacją prędkości, użyj James Newtonking ' s Json.Net biblioteka ( 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);
 4
Author: LandedGently,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-14 17:51:10
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;
 4
Author: Iman Abidi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-04 07:32:55

Możesz to zrobić elegancko poprzez linq tak:

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

Lub jak dynamiczne linq to (Asdynamiczne jest wywoływane bezpośrednio na zbiorze danych):

TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M)
Wolę ostatnie podejście, podczas gdy jest najbardziej elastyczne. P. S.: nie zapomnij połączyć System.Data.DataSetExtensions.dll reference
 3
Author: AuthorProxy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-06 09:44:54

Dla VB.NET kod będzie wyglądał tak:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
 3
Author: Abdul Saboor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 04:07:40

Przykład jak to osiągnąć podany poniżej:

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();
 3
Author: Ryan Gavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-25 16:04:52

Spróbuj tego...

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 );
}
 2
Author: Uthaiah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-20 14:17:10

Możesz spróbować tego, ale musisz być pewien, jaki typ wartości dla każdej kolumny

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"),    
});
 2
Author: Gabriel Martinez Bustos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-25 14:33:48