programing

데이터 테이블에 대한 LINQ 쿼리

muds 2023. 5. 26. 22:50
반응형

데이터 테이블에 대한 LINQ 쿼리

DataTable 개체에 대해 LINQ 쿼리를 수행하려고 하는데 이상하게도 DataTable에서 이러한 쿼리를 수행하는 것이 쉽지 않습니다.예:

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

이것은 허용되지 않습니다.이와 같은 것을 어떻게 작동시킬 수 있습니까?

LINQ 쿼리가 데이터 테이블에서 허용되지 않는다는 것이 놀랍습니다!

다음에 대해 쿼리할 수 없습니다.DataTable의 Rows 컬렉션, 이후DataRowCollection하지 않습니다IEnumerable<T>은 사을용합니다야를 해야 합니다.AsEnumerable()의 내선 DataTable이와 같은 경우:

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

@Keith가 말했듯이 System에 대한 참조를 추가해야 합니다.데이터.데이터 세트 확장

AsEnumerable()아온다를 합니다.IEnumerable<DataRow>▁to▁need▁you▁▁if를 변환해야 하는 경우IEnumerable<DataRow>DataTable을 사용합니다.CopyToDataTable()연장의

아래는 람다 식에 대한 쿼리입니다.

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는 Linkq 쿼리를 수행할 수 있는 IQueryable 및 일반 IEnumberable 구조를 사전에 생성한 것입니다.

두 인터페이스 모두 몇 가지 정렬 유형 안전 검증이 필요합니다.데이터 테이블의 형식이 강력하지 않습니다.예를 들어, 이것은 사람들이 배열 목록에 대해 쿼리할 수 없는 이유는 다음과 같습니다.

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

@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

저는 이에 대해 몇 번이나 답했다는 것을 알고 있지만, 다른 접근 방식을 제공하기 위해서입니다.

나는 그것을 사용하는 것을 좋아합니다..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);

처럼, 은 필요 .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")                         
                    };

이름 및 기간 필드는 이제 쿼리 개체의 일부이며 콘솔과 같이 액세스할 수 있습니다.라인 쓰기(query.name );

LINQ를 사용하여 데이터 세트/데이터 테이블의 데이터 조작

var results = from myRow in tblCurrentStock.AsEnumerable()
              where myRow.Field<string>("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper())
              select myRow;
DataView view = results.AsDataView();
//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 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 = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)

특정 값을 원하는 경우:

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

사용해 보세요.

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

대부분의 경우 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를 사용하는 것은 매우 느립니다.속도 최적화에 관심이 있다면 James Newtonking의 Json을 사용하십시오. 라이브러리(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

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

저는 다음과 같은 해결책을 제안합니다.

DataView view = new DataView(myDataTable); 
view.RowFilter = "RowNo = 1";
DataTable results = view.ToTable(true);

DataView 설명서에서 가장 먼저 확인할 수 있는 내용은 다음과 같습니다.

정렬, 필터링, 검색, 편집 및 탐색을 위한 데이터 테이블의 사용자 정의된 데이터 바인딩 가능 보기를 나타냅니다.

DataTable은 데이터만 저장하기 위한 것이며 DataView를 통해 DataTable에 대해 "쿼리"할 수 있습니다.

이 경우에는 다음과 같이 작동합니다.

SQL 문을 구현하려고 합니다.

SELECT *
FROM myDataTable
WHERE RowNo = 1

"데이터 테이블 언어"로 표시됩니다.C#에서는 다음과 같이 읽습니다.

FROM myDataTable
WHERE RowNo = 1
SELECT *

다음과 같이 C#으로 표시됩니다.

DataView view = new DataView(myDataTable);  //FROM myDataTable
view.RowFilter = "RowNo = 1";  //WHERE RowNo = 1
DataTable results = view.ToTable(true);  //SELECT *

언급URL : https://stackoverflow.com/questions/10855/linq-query-on-a-datatable

반응형