I have a datable with 50 rows and has an ID Column. I am trying to get an array that holds only the IDs like:
string [] IDs = (from row in DataTable.Rows
select row["ID"].toString()).ToArray();
Is there a way to do this. I always get the error "Could not find he implementation of the query...."
Use the DataTableExtensions.AsEnumerable method by adding a reference to System.Data.DataSetExtensions and a using System.Data; Then you should be able to use the following query:
var query = from row in datatable.AsEnumerable()
select row["ID"].ToString();
string[] ids = query.ToArray();
If you really need an array you can use the last line above or enclose the query in parentheses and call ToArray() as you did originally. I'm generally not a fan of the latter approach.
In fluent syntax it would be:
string[] ids = datatable.AsEnumerable()
.Select(row => row["ID"].ToString())
.ToArray();
is there is anyway you can select a list data table into a customer object array. Assuming all the columns are going to be same.
Related
I want to group by a datatable by the columns which are present in a List. Moreover I want to sum a column using group by result.
How to create a dynamic linq query for this?
In case you want to use a dynamic linq query for this, you can use System.Linq.Dynamic.Core.
The code could look like:
var result = context.Posts.GroupBy("BlogId").Select("new(Key, Sum(NumberOfReads) AS TotalReads)");
See also
https://dynamic-linq.net/basic-query-operators#groupby-by-a-single-key-and-do-a-sum
Just group by the identifier you need and then sum the column as below.
var lstYourClass = lstYourClass .GroupBy(x => x.Id).Select(z => new YourClassType
{
Amount= z.Sum(a => a.Amount),
}).ToList();
Hope it helps :)
I have a data table tblWorkList with multiple columns: RecordNr, GroupNum, Section, SubscriberID, and quite a few others.
What I need to do is create a dataview or second datatable that is the equivalent of:
SELECT SubscriberID FROM tblWorkList GROUP BY SubscriberID;
I'm doing it in the application because I need this to end up in a dataview that will then be filtered based on multiple user inputs. I have that part working. I've spent several hours now beating my head against the internet trying to figure out how to do this, but I keep running up against errors in solutions that LOOK like they should work but end up failing spectacularly. Although, that said, I'm VERY inexperienced with LINQ right now, so I'm sure I'm missing something pretty straightforward.
(The basic functionality is this: The table contains a list of records to be processed. Basically, I need to take the table full of records, pull the subscriber IDs into a dataview, allow the user to filter that dataview down by a variety of methods (and providing the user a running count of the number of SubscriberID's matching the selected criteria), and when they're done, assign all of the records associated with the resulting SubscriberID collection to a specific analyst to be processed.)
All of the methods I've attempted to use to create the list or dataview of SubscriberID values are enclosed in this:
using (DataTable dt = dsWorkData.Tables["tblWorkData"])
The table tblWorkData contains approximately 23,000 records.
Here are several of my attempts.
Attempt 1 - Error is
Parameter may not be null. Parameter: source'
var result1 = from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select new { SubscriberID = grp.Key };
ShowMessage(result1.Count().ToString());
Attempt 2 - Error is
'Cannot implicitly convert anonymous type: string SubscriberID to DataRow'
EnumerableRowCollection<DataRow> query =
from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select new { SubscriberID = grp.Key };
Attempt 3 - Error is
'The [third] name 'row' does not exist in the current context.'
EnumerableRowCollection<DataRow> query2 =
from row in dt.AsEnumerable()
group row by row.Field<string>("SubscriberID") into grp
select row;
Attempt 4 - same error as Attempt 1:
DataTable newDt = dt.AsEnumerable()
.GroupBy(r => new { SubscriberID = r["SubscriberID"] })
.Select(g => g.OrderBy(r => r["SubscriberID"]).First())
.CopyToDataTable();
MessageBox.Show(newDt.Rows.Count.ToString());
Attempt 5 - same error as Attempt 1:
var result = dt.AsEnumerable().GroupBy(row => row.Field<string>("SubscriberID"));
MessageBox.Show(result.Count().ToString());
Attempt 6 - same error as Attempt 1:
var results = dt.AsEnumerable().GroupBy(g => g["SubscriberID"])
.Select(x => x.First());
MessageBox.Show(results.Count().ToString());
So can someone explain what I'm doing wrong here, or at least point me in the right direction? I don't really care WHICH approach gets used, for the record, as long as there's a way to do this.
Answer was a pair of comments from NetMage:
Your SQL query is really using GROUP BY to do DISTINCT, so just use the LINQ Distinct: dt.AsEnumerable().Select(r => r.Field<string>("SubscriberID") ).Distinct().
PS Your first error implies that dt is null - source is the parameter name to AsEnumerable.
I'm trying to select a distinct values from a DataTable using Linq. The DataTable gets populated from an excel sheet which has dynamic column apart from each excel sheet has a column name SERIAL NUMBER which is mandatory.
I have a DataTable for demo purpose which consist of 4 serial number as:
12345
12345
98765
98765
When I do
var distinctList = dt.AsEnumerable().Select(a => a).Distinct().ToList();
If I do
var distinctList = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER").Distinct().ToList();
Then I get the correct results, however but it only contains the one column from dt and not all the other columns
I get all four records instead of 2. Can someone tell me where I'm going wrong please.
The problem is that Distinct method by default uses the default equality comparer, which for DataRow is comparing by reference. To get the desired result, you can use the Distinct overload that allows you to pass IEqualityComparer<T>, and pass DataRowComparer.Default:
The DataRowComparer<TRow> class is used to compare the values of the DataRow objects and does not compare the object references.
var distinctList = dt.AsEnumerable().Distinct(DataRowComparer.Default).ToList();
For more info, see Comparing DataRows (LINQ to DataSet).
So, you want to group them by Serial Number and retrieve the full DataRow? Assuming that after grouping them we want to retrieve the first item:
var distinctList = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER"))
.Select(a => a.FirstOrDefault()).Distinct().ToList();
EDIT: As requested
var distinctValues = dt.AsEnumerable().Select(a => a.Field<string>("SERIAL NUMBER")).Distinct().ToList();
var duplicateValues = dt.AsEnumerable().GroupBy(a => a.Field<string>("SERIAL NUMBER")).SelectMany(a => a.Skip(1)).Distinct().ToList();
var duplicatesRemoved = dt.AsEnumerable().Except(duplicateValues);
In ToTable method the first parameter specifies if you want Distinct records, the second specify by which column name we will make distinct.
DataTable returnVals = dt.DefaultView.ToTable(true, "ColumnNameOnWhichYouWantDistinctRecords");
Here there is no need to use linq for this task !
Using Linq a GroupBy would be better suited, by the sounds of it.
var groups = dt.AsEnumerable().GroupBy(a => a.SerialNumber).Select(_ => new {Key = _.Key, Items = _});
This will then contain groupings based on the Serial Number. With each group of items having the same serial number, but other property values different.
Try this:
List<string> distinctValues = (from row in dt.AsEnumerable() select row.Field<string>("SERIAL NUMBER")).Distinct().ToList();
However to me this also works:
List<string> distinctValues = dt.AsEnumerable().Select(row => row.Field<string>("SERIAL NUMBER")).Distinct().ToList();
I have a linq query which is giving me desired output :
var data = (from c in dtskip.AsEnumerable()
select new[] {
c.Field<string>("Suburb"), c.Field<string>("Postcode"), c.Field<string>("State"),c.Field<string>("ID"), c.Field<string>("SEARCHKEY"), c.Field<string>("RATING"), c.Field<string>("DELIVERY")
});
How can i select all the column instead of giving name like c.field<string>("postcode") .My output is the data only from datatable dtskip :
output:
["DARWIN","0800","NT","2","DARWINNT","A","Delivery Area"]
,["ALAWA","0810","NT","5","ALAWANT","A","Delivery Area"],
["BRINKIN","0810","NT","6","BRINKINNT","A","Delivery Area"],
is there any other way i can get the output in dis way from datatable using linq query .
DataRow contains an ItemArray member which returns all the data in that row as an array, the downside is they are all returned as objects but if all your columns are the same type you can cast the ItemArray in line to the desired type (in this case string)
dtskip.Rows.Cast<DataRow>().Select(r => r.ItemArray.Cast<string>());
This will give you an IEnumerable<IEnumerable<string>> to work with.
have you tried
var data = (From c in dtskip
select c).AsEnumerable(); //Not sure about the AsEnumerable :s
Are you looking for something like this?
var data = dtskip.AsEnumerable().
Select(x => new
{
Suburb = x.Field<string>("Suburb"),
Postcode= x.Field<string>("Postcode"),
State= x.Field<string>("State"),
Id= x.Field<string>("ID"),
Searchkey = x.Field<string>("SEARCHKEY"),
Rating = x.Field<string>("RATING"),
Delivery = x.Field<string>("DELIVERY")
});
Is there an easier way to achieve the following?
var obj = from row in table.AsEnumerable()
select row["DOUBLEVALUE"];
double[] a = Array.ConvertAll<object, double>(obj.ToArray(), o => (double)o);
I'm extracting a column from a DataTable and storing the column in an array of doubles.
Assume that table is a DataTable containing a column called "DOUBLEVALUE" of type typeof(Double).
var obj = (from row in table.AsEnumerable()
select row.Field<double>("DOUBLEVALUE")).ToArray();
The .ToArray() bit is optional, of course; without the ToArray(), you'll get an enumerable sequence of doubles instead of an array - it depends whether you need to read it once or twice. If you have nulls in the data, use <double?> instead.
(note that this needs a reference to System.Data.DataSetExtensions.dll, and a "using System.Data;" statement - this brings the .Field<T>(...) extension methods into play)
double[] a = (from row in table.AsEnumerable()
select Convert.ToDouble( row["DOUBLEVALUE"] )).ToArray();
If you have rows that may have null values for that column, add where row["DOUBLEVALUE"] != null before the select.