Development Tip

DataTable에 대한 LINQ 쿼리

yourdevel 2020. 9. 27. 14:06
반응형

DataTable에 대한 LINQ 쿼리


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

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

이것은 허용되지 않습니다. 이런 식으로 작동하려면 어떻게해야합니까?

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


구현하지 않으므로 DataTableRows 컬렉션 에 대해 쿼리 할 수 ​​없습니다 . 에 대한 확장자 를 사용해야합니다 . 이렇게 :DataRowCollectionIEnumerable<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>A를 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);

주석에서 언급했듯이 Linq의 일부이므로 다른 어셈블리가 필요하지 않습니다 ( 참조 )


//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 (정의 된 열 포함 : 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);

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

                ICommonExtService commonExtService = ProxyHelper.GetCommonExtServiceProxy();

                filledJSON = commonExtService.GetCandidateData(candidateCode.Trim());
                JObject CanidateDataObj = new JObject();
                if (string.IsNullOrEmpty(filledJSON) == false)
                {
                    DataTable dt = new DataTable();

                    dt = JsonConvert.DeserializeObject<DataTable>(filledJSON);

                    DataTable DtC = dt.Clone();

                    foreach (DataColumn column in DtC.Columns)
                    {
                        column.DataType = typeof(string);
                    }
                    foreach (DataRow row in dt.Rows)
                    {
                        DtC.ImportRow(row);
                    }

                    try
                    {
                        if (DtC != null && DtC.Columns.Count > 0 && DtC.Rows.Count > 0)
                        {
                            //Json Formating code
                            var filter = (from r1 in DtC.AsEnumerable()
                                          group r1 by new
                                          {
                                              CandidateCode = r1.Field<string>("CandidateCode"),
                                              FirstName = r1.Field<string>("FirstName"),
                                              MiddleName = r1.Field<string>("MiddleName"),

                                              LastName = r1.Field<string>("LastName"),
                                              FullName = r1.Field<string>("FullName"),

                                              DistributionCode = r1.Field<string>("DistributionCode"),
                                              GoCode = r1.Field<string>("GoCode"),
                                              SSN = r1.Field<string>("SSN")

                                          } into g
                                          select new
                                          {

                                              FirstName = g.Key.FirstName,
                                              MiddleName = g.Key.MiddleName,
                                              LastName = g.Key.LastName,
                                              FullName = g.Key.FullName,
                                              CandidateCode = g.Key.CandidateCode,
                                              DistributionCode = g.Key.DistributionCode,
                                              GoCode = g.Key.GoCode,
                                              SSN = g.Key.SSN,

                                              AddressList = from a1 in g.ToList().
                                                          Where(e1 => (e1.Field<string>("AddressLine1") == ""
                                                          && e1.Field<string>("State") == ""
                                                          && e1.Field<string>("City") == ""
                                                          && e1.Field<string>("ZipCode") == ""
                                                          && e1.Field<string>("County") == ""
                                                          && e1.Field<string>("Country") == "") == false
                                                          )
                                                            group a1 by new
                                                            {
                                                                AddressLine1 = a1.Field<string>("AddressLine1"),
                                                                State = a1.Field<string>("State"),
                                                                City = a1.Field<string>("City"),
                                                                ZipCode = a1.Field<string>("ZipCode"),
                                                                County = a1.Field<string>("County"),
                                                                Country = a1.Field<string>("Country")
                                                            } into f
                                                            select new
                                                            {
                                                                AddressLine1 = f.Key.AddressLine1,
                                                                State = f.Key.State,
                                                                City = f.Key.City,
                                                                ZipCode = f.Key.ZipCode,
                                                                County = f.Key.County,
                                                                Country = f.Key.Country
                                                            },

                                              EmploymentHistoryList = from e1 in g.ToList().
                                                          Where(e1 => (e1.Field<string>("EmployerName") == ""
                                                          && e1.Field<string>("JobTitle") == ""
                                                          && e1.Field<string>("City") == ""
                                                          && e1.Field<string>("State") == ""
                                                          && e1.Field<string>("County") == ""
                                                          && e1.Field<string>("ZipCode") == ""
                                                          && e1.Field<string>("ManagerFirstName") == ""
                                                          && e1.Field<string>("ManagerLastName") == "") == false
                                                          )
                                                                      group e1 by new
                                                                      {
                                                                          EmployerName = e1.Field<string>("EmployerName"),
                                                                          JobTitle = e1.Field<string>("JobTitle"),
                                                                          City = e1.Field<string>("City"),
                                                                          State = e1.Field<string>("State"),
                                                                          County = e1.Field<string>("County"),
                                                                          ZipCode = e1.Field<string>("ZipCode"),
                                                                          ManagerFirstName = e1.Field<string>("ManagerFirstName"),
                                                                          ManagerLastName = e1.Field<string>("ManagerLastName")
                                                                      } into h
                                                                      select new
                                                                      {
                                                                          EmployerName = h.Key.EmployerName,
                                                                          JobTitle = h.Key.JobTitle,
                                                                          City = h.Key.City,
                                                                          State = h.Key.State,
                                                                          County = h.Key.County,
                                                                          ZipCode = h.Key.ZipCode,
                                                                          ManagerFirstName = h.Key.ManagerFirstName,
                                                                          ManagerLastName = h.Key.ManagerLastName
                                                                      }

                                          });

                            if (filter != null)
                            {
                                JArray jr = JArray.FromObject(filter);
                                CanidateDataObj = (JObject)jr[0];
                            }
                            if (_responsemsg.Content == null && CanidateDataObj.HasValues == true)
                            {

                                ResponseData = new JObject();
                                ResponseData.Add("ResponseCode", ResponseCode.Success.ToString());
                                ResponseData.Add("ResponseMessage", "Data present");
                                ResponseData.Add("Data", CanidateDataObj);
                                _responsemsg.StatusCode = System.Net.HttpStatusCode.OK;
                                _responsemsg.Content = new ObjectContent<JObject>(ResponseData, formatter, "application/json");
                                return _responsemsg;
                            }
                        }
                        else
                        {
                            ResponseData = new JObject();
                            ResponseData.Add("responseCode", ResponseCode.Failure.ToString());
                            ResponseData.Add("responseMessage", "No candidate found with given Code");
                            _responsemsg.StatusCode = System.Net.HttpStatusCode.NotFound;
                            _responsemsg.Content = new ObjectContent<JObject>(ResponseData, formatter, "application/json");
                            return _responsemsg;
                        }
                    }
                    catch (Exception Ex)
                    {
                        ResponseData = new JObject();
                        ResponseData.Add("responseCode", ResponseCode.Failure.ToString());
                        ResponseData.Add("responseMessage", Ex.Message.ToString());
                        _responsemsg.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                        _responsemsg.Content = new ObjectContent<JObject>(ResponseData, formatter, "application/json");
                        return _responsemsg;
                    }

                }
                else if(string.IsNullOrEmpty(candidateCode)==false)
                {
                    ResponseData = new JObject();
                    ResponseData.Add("responseCode", ResponseCode.Failure.ToString());
                    ResponseData.Add("responseMessage", "No candidate found with given Code");
                    _responsemsg.StatusCode = System.Net.HttpStatusCode.NotFound;
                    _responsemsg.Content = new ObjectContent<JObject>(ResponseData, formatter, "application/json");
                    return _responsemsg;

                }
                else
                {
                    ResponseData = new JObject();
                    ResponseData.Add("responseCode", ResponseCode.Failure.ToString());
                    ResponseData.Add("responseMessage", "Please provide valid candidate code");
                    _responsemsg.StatusCode = System.Net.HttpStatusCode.BadRequest;
                    _responsemsg.Content = new ObjectContent<JObject>(ResponseData, formatter, "application/json");
                    return _responsemsg;
                }

다음 솔루션을 제안합니다.

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

Looking at the DataView Documentation, the first thing we can see is this:

Represents a databindable, customized view of a DataTable for sorting, filtering, searching, editing, and navigation.

What I am getting from this is that DataTable is meant to only store data and DataView is there enable us to "query" against the DataTable.

Here is how this works in this particular case:

You try to implement the SQL Statement

SELECT *
FROM myDataTable
WHERE RowNo = 1

in "DataTable language". In C# we would read it like this:

FROM myDataTable
WHERE RowNo = 1
SELECT *

which looks in C# like this:

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

반응형