Запрос LINQ в DataTable
Я пытаюсь выполнить запрос LINQ в объекте DataTable, и я прихожу к выводу, что выполнение таких запросов в DataTables непросто. Например:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
Это запрещено. Как мне получить что-то вроде этого?
Я поражен тем, что запросы LINQ не разрешены в DataTables!
Ответы
Ответ 1
Вы не можете выполнять запросы к коллекции строк DataTable
, поскольку 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>
в DataTable
, используйте расширение CopyToDataTable()
.
Ниже приведен запрос с лямбда-выражением,
var result = myDataTable
.AsEnumerable()
.Where(myRow => myRow.Field<int>("RowNo") == 1);
Ответ 2
var results = from DataRow myRow in myDataTable.Rows
where (int)myRow["RowNo"] == 1
select myRow
Ответ 3
Не то, чтобы они не были преднамеренно запрещены в DataTables, это только то, что DataTables предваряют IQueryable и общие конструкторы IEnumerable, по которым могут выполняться запросы Linq.
Оба интерфейса требуют некоторой проверки безопасности типа. Таблицы данных не строго типизированы. Это по той же причине, почему люди не могут запрашивать ArrayList, например.
Для работы Linq вам нужно сопоставить ваши результаты с объектами, защищенными типом, и запросить их вместо этого.
Ответ 4
Как сказал @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
Ответ 5
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")
};
Ответ 6
Я понимаю, что на это уже отвечали несколько раз, но просто чтобы предложить другой подход:
Мне нравится использовать метод .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 (Ссылка)
Ответ 7
//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();
//
Ответ 8
Использование 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();
Ответ 9
Попробуйте эту простую строку запроса:
var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field<int>("RowNo") == 1);
Ответ 10
Вы можете использовать LINQ для объектов в коллекции Rows, например:
var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow;
Ответ 11
Попробуйте это
var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ;
Ответ 12
Скорее всего, классы для DataSet, DataTable и DataRow уже определены в решении. В этом случае вам не понадобится ссылка на DataSetExtensions.
Ex. Класс DataSet name-> CustomSet, класс DataRow name-> 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);
Ответ 13
Это простой способ, который работает для меня и использует лямбда-выражения:
var results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1)
Затем, если вы хотите получить определенное значение:
if(results != null)
var foo = results["ColName"].ToString()
Ответ 14
var results = from myRow in myDataTable
where results.Field<Int32>("RowNo") == 1
select results;
Ответ 15
В моем приложении я обнаружил, что использование 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);
Ответ 16
Пример того, как это сделать, приведен ниже:
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();
Ответ 17
Для VB.NET Код будет выглядеть так:
Dim results = From myRow In myDataTable
Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow
Ответ 18
Попробуйте это...
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 );
}
Ответ 19
IEnumerable<string> result = from myRow in dataTableResult.AsEnumerable()
select myRow["server"].ToString() ;
Ответ 20
Вы можете заставить его работать элегантно с помощью 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)
Я предпочитаю последний подход, пока он является наиболее гибким.
P.S.: Не забудьте подключить System.Data.DataSetExtensions.dll
ссылку
Ответ 21
Вы можете попробовать это, но вы должны быть уверены, что тип значений для каждого столбца
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"),
});
Ответ 22
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;
}
Ответ 23
Я предлагаю следующее решение:
DataView view = new DataView(myDataTable);
view.RowFilter = "RowNo = 1";
DataTable results = view.ToTable(true);
Глядя на документацию DataView, первое, что мы можем увидеть, это:
Represents a databindable, customized view of a DataTable for sorting, filtering, searching, editing, и navigation.
Из этого я получаю то, что DataTable предназначен только для хранения данных, а DataView позволяет нам "запрашивать" данные из DataTable.
Вот как это работает в данном конкретном случае:
Вы пытаетесь реализовать оператор SQL
SELECT *
FROM myDataTable
WHERE RowNo = 1
в "DataTable язык". В С# мы читаем это так:
FROM myDataTable
WHERE RowNo = 1
SELECT *
который выглядит в С# следующим образом:
DataView view = new DataView(myDataTable); //FROM myDataTable
view.RowFilter = "RowNo = 1"; //WHERE RowNo = 1
DataTable results = view.ToTable(true); //SELECT *