I have a DataTable I am populating from SQL table with the following example columns
ID
Type
Value
I am populating the DataTable with rows which are of a certain type. I want to select the rows 10 - 20 from my resulting DataTable:
Connect conn = new Connect();
SqlDataAdapter da = new SqlDataAdapter(SQL, conn.Connection());
//Creates data
DataTable d = new DataTable();
da.Fill(d);
DataRow[] result = d.Select();
In the above code I have omitted the main SQL, and currently I have no select for my DataRow array. I cannot find a way to reference the row numbers.
So for instance I am looking for something like Select("rownum > X && rownum < Y")
I have searched here, and a number of other resources to no avail. Any clues would be really handy, or just a simple not possible.
It's always better to select only what you need from the database(f.e. by using the TOP clause or a window function like ROW_NUMBER) instead of filtering it in memory.
However, you can use Linq-To-DataSet and Enumerable.Skip + Enumerable.Take:
var rows = d.AsEnumerable()
.Skip(9).Take(11); // select rows 10-20 as desired (so you want 11 rows)
If you want a new DataTable from the filtered result use CopyToDataTable, if you want a DataRow[] use rows.ToArray().
I would just do the 'take' and 'skip' command and keep it simple:
d.Select().Skip(10).Take(10); // skips 10 rows, then selects ten after that.
This would be assuming you have the Linq using set (using System.Linq)
Related
I am assigning data to a Dataset manually from the data of another Dataset, in which two conditions are met one when there is data from another Dataset where the date field matches the rows with this data, otherwise I add them as a new row. This is perfect.
The problem is that when you finish assigning the data to the Dataset, the data that shows first are the ones that are updated with the first condition.
I need the data to be sorted by Date either dd\MM\yyyy or yyyy/MM/dd without taking into account the hours, and regardless of whether it was updated or added, but to order it by Date of ASC mode.
//foreach (DataRow dr in ds.Tables[0].Rows)
foreach (DataRow dr in ds.Tables[0].AsEnumerable().OrderBy(x=>x.Field<DateTime>("date").Date).ToList())
{
var row=dataset_manually.Tables[0].AsEnumerable().Where(x=> x.Field<DateTime>("date").Date == ((DateTime)dr["date"]).Date).FirstOrDefault();
if (row!=null)
{
//Update the data
row["entryToTurn"]=(DateTime)dr["entryToTurn"];
row["departureToTurn"]=(DateTime)dr["departureToTurn"];
row["turn"]=dr["turn"].ToString();
}
else
{
//Add new rows
var row2= dataset_manually.Tables[0].NewRow();
row2["entryToTurn"] = dr["entryToTurn"];
row2["departureToTurn"] = dr["departureToTurn"];
row2["turn"] = dr["turn"].ToString();
dataset_manually.Tables[0].Rows.Add(fila2);
}
}
For some reason the OrderBy in the foreach does not work. adds the data but does not order it. foreach (DataRow dr in ds.Tables[0].AsEnumerable().OrderBy(x=>x.Field<DateTime>("date").Date).ToList())
I tried this but it did not work:
dataset_manually.Tables[0].DefaultView.Sort = "date asc";
And I can not do it like this:
datagridview1.Sort(datagridview1.Columns[0], ListSortDirection.Ascending);
Because this only shows the data ordered in the DataGridView but when using the Dataset in another side the data is not sorted and the positions of the values in the grid are not the same things in the Dataset.
Desired output:
Note: The data is NOT assigned by the index, it must be assigned where the date field matches
Environment: Visual Studio 2010 (WindowsForms C#) & .NET NetFramework 4
Your code is not working because you first sort your data set and then you add new rows to it (so after everything)
Solution for this is slow if you have a lot of rows inside data set so I AM RECOMMENDING TO DO NOT DO THIS BUT SORT DATA AFTER LOADING IT INTO CODE.
Solution to this problem could be:
Load Data from DB into dataGridView
Get dataSource from dataGridView as DataTable
Add new data to DataTable
Sort DataTable
Save sorted data
Sorting could be done with:
DataView dv = data.DefaultView;
dv.Sort = "PrimaryColumn asc" //desc for descending
data = dv.ToTable();
I have two tables with some odd join behavior. Here is a brief schema with data:
CREATE TABLE object(vnum INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE object_affect(vnum INTEGER, apply_id INTEGER, modifier INTEGER);
object
vnum name
10404 Test Item
object_affect
vnum apply_id modifier
10404 1 4
10404 5 2
10404 12 6
If I run the below query I should have 3 rows returned however it only returns 1 row.
select * from object o
inner join object_affect oa on oa.vnum = o.vnum
where o.vnum = 10404
If I change the query to this (change * to oa.vnum).. it return 3 rows:
select oa.vnum from object o
inner join object_affect oa on oa.vnum = o.vnum
where o.vnum = 10404
Also, if I remove the "PRIMARY KEY" flag in the create table statement from the vnum field on object table the first query that only returned one 1 returns all 3 joined rows correctly.
What am I missing that causes the first query to not return 3 rows of joined data?
I ran into this again 3.5 years later. I wanted to share the solution. The idea in this case is that the DataTable is used to display the results of a query on some kind of control, a DataGrid, etc. As a result, it doesn't need the constraints the DataTable tries to infer from the database about unique keys, etc. There's no good way to disable the constraints on the DataTable that I've found by itself but you can couple it with a DataSet and do just that. This snippet (assuming the SqliteCommand is already setup) works:
using (var dr = cmd.ExecuteReader())
{
var dt = new DataTable();
using (var ds = new DataSet() { EnforceConstraints = false })
{
ds.Tables.Add(dt);
dt.BeginLoadData();
dt.Load(dr);
dt.EndLoadData();
ds.Tables.Remove(dt);
}
}
Basically we temporarly use the DataSet and then discard it (it is important to remove it from the DataSet so the DataSet can Dispose and be garbage collected). Then you can keep the DataTable and persist it to bind it to a control.
I am trying to perform a two-pass search against a Sharepoint list. In the first pass, I am using a KeywordQuery to search against the index of all the items. In the second pass, I am applying column value filters chosen by a user by building a select statement.
ResultTableCollection rtc = kwqry.Execute();
ResultTable rt = rtc[ResultType.RelevantResults];
dt = new DataTable();
//Load Data Table
dt.Load(rt, LoadOption.OverwriteChanges);
DataRow[] rows = dt.Select("ColumnName1 = 'foo' AND ColumnName2 = 'bar'");
Where the columns could be multi-value lookup columns in a Sharepoint list. The first pass is working properly and returning the right number of matches in a DataTable. However, when I try to apply the Select statement, I get the following error: Cannot perform '=' operation on System.String[] and System.String. Converting the columns to a string instead of a string array results in the same error, as does using the IN operator.
Am I building my select statement incorrectly? How could I run my second pass filter on my DataTable?
Have you tried with LINQ?
DataTable t1 = new DataTable();
var rows = from x in t1.AsEnumerable()
where x.Field<string[]>("column1name").Contains("foo")
select x;
You have to specify the field type in the Where clause...
Hope it helps.
Try using this, it will work :
DataRow[] rows = dt.Select("(ColumnName1 = 'foo' AND ColumnName2 = 'bar')");
I have a DataGridView that has a DataTable bound to it, populated from PostgreSQL database with Npgsql .NET data provider library.
Populating records works, but when I want to append just a single records to already existing DataTable, previous records vanish:
NpgsqlDataAdapter npDataAdapterSingle = new NpgsqlDataAdapter("SELECT * from \"Weight\" ORDER BY id DESC LIMIT 1", this.npConnection);
DataTable tmpTable = new DataTable("tmpTable");
npDataAdapterSingle.Fill(tmpTable);
DSWeight.WeightRow row = this.dSWeight.Weight.NewWeightRow();
row.ItemArray = tmpTable.Rows[0].ItemArray;
this.dSWeight.Weight.Rows.InsertAt(row, 0); //Prepend, but i also tried this.dsWeight.Weight.Rows.Add(row);
If I select all records, without LIMIT'ing, then it works as expected. But I thought - why would i need to query the database all over again if I already have those records? That's why I want to LIMIT.
Maybe there is another solution, because I manually add new records to database and query them to add them to datatable, not the way it is supposed to be: add new records to datatable and them to database. I do it this way because I want the database to manage the id and timestamp fields and have datagridview to have these fields populated.
What am I missing?
Am not sure about the data type of DSWeight.WeightRow and the scope of 'this' object since I get to see only a portion of the code and not the full method. This should probably work for you. please have a try.
NpgsqlDataAdapter npDataAdapterSingle = new NpgsqlDataAdapter("SELECT * from \"Weight\" ORDER BY id DESC LIMIT 1", this.npConnection);
DataTable tmpTable = new DataTable("tmpTable");
npDataAdapterSingle.Fill(tmpTable);
row = tmpTable.NewRow();
foreach (DataColumn col in tmpTable.Columns)
row[col.ColumnName] = tmpTable.Rows[0][col.ColumnName];
tmpTable.Rows.Add(row, 0);
I have a DataTable available with me which contains thousands of rows. There is a column called EmpID which is containing '0' for some of the rows. I want to remove them from my current DataTable and want to create a new correct DataTable. I cannot go row by row checking it since it contains huge amount of data. Give me a suggestion to overcome this problem.
the best way would be to filter it at source (if possible) - so if you are creating it from a db, exclude all 0 values in your sql query itself using a where
starting .net 2.0, ms enhanced the filtering logic on the datatable to a great extent. so if you used the dataview (on top of your datatable) and added the where clause in there and added some sort of runtime indexes on this field, it would give you the desired results without looping over all records
You can use DataTable.Select("EmpID <> 0"). This will return an array of DataRows which you can create your new DataTable from if required.
Isn't it possible to first select the rows with EmpID = 0 and then iterate over these only ?
DataTable newTable = new DataTable();
foreach (DataRow dr in oldTable.Select("EmpID = '0'")) {
newTable.Rows.Add(dr);
oldTable.Rows.Remove(dr);
}
You can try
DataRow[] temp=
table.Select("EmpID ='0'");
foreach(DataRow dr in temp)
{
table.Rows.Remove(dr);
}
table.acceptchanges();