문제

DataTable 개체에 대해 LINQ 쿼리를 수행하려고 하는데 이상하게도 DataTables에서 이러한 쿼리를 수행하는 것이 간단하지 않다는 것을 알게 되었습니다.예를 들어:

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

이는 허용되지 않습니다.이와 같은 작업을 어떻게 수행합니까?

DataTables에서는 LINQ 쿼리가 허용되지 않는다는 사실에 놀랐습니다!

도움이 되었습니까?

해결책

다음 항목에 대해 쿼리할 수 없습니다. DataTable'에스 수집, 이후 DataRowCollection 구현하지 않습니다 IEnumerable<T>.당신은 AsEnumerable() 확장자 DataTable.다음과 같습니다:

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() 확대.

아래는 Lambda 표현식을 사용한 쿼리입니다.

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

다른 팁

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

DataTables에서 의도적으로 허용되지 않은 것이 아니라 DataTables가 Linq 쿼리를 수행할 수 있는 IQueryable 및 일반 IEnumerable 구문보다 앞서 있다는 것입니다.

두 인터페이스 모두 일종의 유형 안전성 검증이 필요합니다.DataTable은 강력한 형식이 아닙니다.예를 들어 사람들이 ArrayList에 대해 쿼리할 수 없는 이유도 마찬가지입니다.

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

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

나는 이것이 몇 번에 걸쳐 답변되었다는 것을 알고 있지만 다른 접근 방식을 제공하기 위해 다음을 사용하고 싶습니다. .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);
//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를 사용하여 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();

다음과 같은 간단한 쿼리를 시도해 보세요.

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

다음과 같이 Rows 컬렉션의 개체에 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()

아마도 DataSet, DataTable 및 DataRow에 대한 클래스가 이미 솔루션에 정의되어 있을 것입니다.이 경우 DataSetExtensions 참조가 필요하지 않습니다.

전.DataSet 클래스 이름-> CustomSet, DataRow 클래스 이름-> CustomTableRow(정의된 열 포함:행아니, ...)

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

내 응용 프로그램에서 답변에서 제안한 대로 DataTable에 대한 AsEnumerable() 확장을 사용하여 LINQ to Datasets를 사용하는 것이 매우 느리다는 것을 발견했습니다.속도 최적화에 관심이 있다면 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);

이를 달성하는 방법에 대한 예는 다음과 같습니다.

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

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

이 시도...

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

다음과 같이 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 참조

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

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"),    
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top