c# - DataTable에 대한 LINQ 쿼리




.net .net-3.5 (18)

대부분 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);

DataTable 개체에 대한 LINQ 쿼리를 수행하려고하는데 기이하게도 DataTable에서 이와 같은 쿼리를 수행하는 것이 쉽지 않은 것으로 나타났습니다. 예 :

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

허용되지 않습니다. 어떻게 작동합니까?

DataTables에서 LINQ 쿼리를 사용할 수 없다는 사실에 놀랐습니다.


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

이것을 시도 할 수는 있지만 각 열의 값 유형을 확인해야합니다

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

마찬가지로 @ 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 프로젝트 참조를 추가해야합니다.


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)

나는 가장 유연한 반면 마지막 접근 방식을 선호합니다. 추신 : System.Data.DataSetExtensions.dll 참조를 연결하는 것을 잊지 마십시오.


내 응용 프로그램에서 응답에서 제안 된 것처럼 DataTable에 대한 AsEnumerable () 확장명이있는 데이터 집합에 LINQ를 사용하면 매우 느립니다. 속도 최적화에 관심이 있으시면 James Newtonking의 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);

이 간단한 쿼리 라인을 사용해보십시오 :

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

다음과 같이 행 컬렉션의 개체에 LINQ를 사용할 수 있습니다.

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

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

이 문제는 몇 번 이상 대답했지만, 또 다른 접근법을 제공하기 위해 .Cast<T>() 메서드를 사용하고 .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);

DataRowCollectionIEnumerable<T> 구현하지 않으므로 DataTableRows 컬렉션에 대해 쿼리 할 수 ​​없습니다. DataTable AsEnumerable() 확장을 사용해야합니다. 이렇게 :

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 results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)

그런 다음 특정 값을 원할 경우 :

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

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

이 시도...

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

이를 달성하는 방법에 대한 예가 아래에 나와 있습니다.

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

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

의도적으로 DataTable에 허용되지 않은 것은 아닙니다. 단지 DataTables가 Linq 쿼리를 수행 할 수있는 IQueryable 및 일반 IEnumerable 구문을 선행한다는 것입니다.

두 인터페이스 모두 일부 정렬 유형 안전성 검증이 필요합니다. DataTable은 강력한 형식이 아닙니다. 이것은 사람들이 ArrayList에 대해 질의 할 수없는 것과 같은 이유입니다.

Linq가 작동하려면 결과를 유형 안전 객체에 매핑하고 그 대신에 쿼리해야합니다.


절대적으로 - 당신은 기본적으로 원하는 :

var results = from p in persons
              group p.car by p.PersonId into g
              select new { PersonId = g.Key, Cars = g.ToList() };

또는 쿼리가없는 표현식으로 :

var results = persons.GroupBy(
    p => p.PersonId, 
    p => p.car,
    (key, g) => new { PersonId = key, Cars = g.ToList() });

기본적으로 그룹의 내용 ( IEnumerable<T> 으로 볼 때)은 주어진 키에 대한 프로젝션 (이 경우 p.car 에 있던 값의 시퀀스입니다.

GroupBy 작동 방식에 대한 자세한 내용 은 주제에 관한Edulinq 게시물을 참조하십시오.

(필자는 .NET에서 명명 규칙 을 따르기 위해 PersonIDPersonIDPersonId 했습니다.)

또는 Lookup 사용할 수도 있습니다.

var carsByPersonId = persons.ToLookup(p => p.PersonId, p => p.car);

그러면 각 사람을위한 차량을 매우 쉽게 얻을 수 있습니다.

// This will be an empty sequence for any personId not in the lookup
var carsForPerson = carsByPersonId[personId];






c# .net linq datatable .net-3.5