LINQ-запрос к DataTable

c# .net linq datatable .net-3.5

858065 просмотра

23 ответа

Я пытаюсь выполнить запрос LINQ для объекта DataTable, и странным образом обнаруживаю, что выполнение таких запросов к объектам DataTable не является простым. Например:

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

Это не разрешено Как мне получить что-то подобное?

Я поражен, что запросы LINQ не разрешены в DataTables!

Автор: Calanus Источник Размещён: 19.08.2019 05:24

Ответы (23)


1230 плюса

Решение

Вы не можете запросить против DataTable«ы Rows коллекции, так как DataRowCollectionне выполняет IEnumerable<T>. Вам нужно использовать AsEnumerable()расширение для DataTable. Вот так:

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

И, как говорит Кит, вам нужно добавить ссылку на System.Data.DataSetExtensions

AsEnumerable()возвращается IEnumerable<DataRow>. Если вам нужно конвертировать IEnumerable<DataRow>в a DataTable, используйте CopyToDataTable()расширение.

Ниже приведен запрос с лямбда-выражением,

var result = myDataTable
    .AsEnumerable()
    .Where(myRow => myRow.Field<int>("RowNo") == 1);
Автор: Collin K Размещён: 14.08.2008 07:45

125 плюса

var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow
Автор: JoelFan Размещён: 05.03.2009 02:53

66 плюса

Дело не в том, что они были намеренно запрещены в DataTables, просто в DataTable предшествуют IQueryable и универсальные конструкции IEnumerable, для которых могут выполняться запросы Linq.

Оба интерфейса требуют некоторой проверки безопасности типа. DataTables не являются строго типизированными. Это та же самая причина, по которой люди, например, не могут запрашивать ArrayList.

Чтобы Linq работал, вам нужно сопоставить результаты с типобезопасными объектами и вместо этого выполнить запрос.

Автор: Jon Limjap Размещён: 14.08.2008 10:10

48 плюса

Как сказал @ 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

Автор: Keith Размещён: 14.08.2008 11:07

38 плюса

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")                         
                    };
Автор: Ravi Размещён: 23.05.2010 04:03

29 плюса

Я понимаю, что на это уже отвечали несколько раз, но просто для того, чтобы предложить другой подход, я хотел бы использовать .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);
Автор: vandsh Размещён: 02.02.2016 09:22

28 плюса

//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();
 // 
Автор: sushil pandey Размещён: 05.01.2012 08:43

27 плюса

Использование 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();
Автор: Salim Размещён: 13.07.2011 11:21

20 плюса

Попробуйте эту простую строку запроса:

var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
Автор: Mohit Verma Размещён: 05.04.2016 09:38

15 плюса

Вы можете использовать LINQ для объектов в коллекции Rows, например так:

var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
Автор: David Wengier Размещён: 14.08.2008 10:11

11 плюса

Попробуй это

var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 
Автор: midhun sankar Размещён: 18.05.2012 07:15

11 плюса

Это простой способ, который работает для меня и использует лямбда-выражения:

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

Тогда, если вы хотите конкретное значение:

if(results != null) 
    var foo = results["ColName"].ToString()
Автор: Matt Kemp Размещён: 18.03.2015 10:13

11 плюса

Скорее всего, классы для DataSet, DataTable и DataRow уже определены в решении. Если это так, вам не понадобится ссылка DataSetExtensions.

Ex. Имя класса 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);
Автор: xadriel Размещён: 24.04.2013 05:17

9 плюса

var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
Автор: Vinay Размещён: 01.02.2014 11:51

7 плюса

В моем приложении я обнаружил, что использование LINQ to Datasets с расширением AsEnumerable () для DataTable, как было предложено в ответе, было чрезвычайно медленным. Если вы заинтересованы в оптимизации скорости, используйте библиотеку Джеймса Ньютонкинга 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);
Автор: LandedGently Размещён: 14.10.2014 05:51

7 плюса

Пример того, как этого добиться, приведен ниже:

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();
Автор: Ryan Gavin Размещён: 25.10.2017 04:04

6 плюса

Для VB.NET код будет выглядеть так:

Dim results = From myRow In myDataTable  
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
Автор: Abdul Saboor Размещён: 17.10.2012 04:04

6 плюса

IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
                             select myRow["server"].ToString() ;
Автор: Iman Abidi Размещён: 04.08.2015 07:32

6 плюса

Попробуй это...

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 );
}
Автор: Uthaiah Размещён: 10.04.2014 10:24

5 плюса

Вы можете заставить его работать элегантно через linq следующим образом:

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

Или как динамический linq this (AsDynamic вызывается непосредственно в DataSet):

TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M)

Я предпочитаю последний подход, пока он самый гибкий. PS: не забудьте подключить System.Data.DataSetExtensions.dllссылку

Автор: AuthorProxy Размещён: 03.11.2013 05:54

5 плюса

Вы можете попробовать это, но вы должны быть уверены, что тип значений для каждого столбца

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"),    
});
Автор: Gabriel Martinez Bustos Размещён: 01.02.2018 09:43

0 плюса

                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;
                }
Автор: chandra rv Размещён: 19.08.2019 09:31

0 плюса

Я предлагаю следующее решение:

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

Глядя на документацию DataView , первое, что мы можем увидеть, это:

Представляет настраиваемое представление DataTable с возможностью привязки к данным для сортировки, фильтрации, поиска, редактирования и навигации.

Из этого я получаю то, что DataTable предназначен только для хранения данных, а DataView позволяет нам «запрашивать» данные из DataTable.

Вот как это работает в данном конкретном случае:

Вы пытаетесь реализовать оператор SQL

SELECT *
FROM myDataTable
WHERE RowNo = 1

в «DataTable язык». В 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 *
Автор: Alan Размещён: 19.08.2019 02:18
32x32