I have a datatable in C# with a "price" column and an "allocation" column, and I need to multiply the price column by the allocation column and put the result in the price column. Is there a way to do with without looping over the table? I have tried something like this:
DataTable dt = getData();
dt.Columns["Price"].Expression = "Allocation * Price";
But obviously this gives me the following exception:
Cannot set Expression property due to circular reference in the expression.
Does anyone know of another way to accomplish this? Thanks beforehand.
You could use a LINQ expression to do it in one line:
dt.Rows.ForEach(x => x["Price"] = (double)x["Price"] * (double)x["Allocation"]);
You could just add another column to the DataTable:
dt.Columns.Add("TotalPrice", typeof(decimal));
dt["TotalPrice"] = "Allocation * Price";
Add a new column whose value is calculated from the other two:
dt.Columns.Add("TotalPrice", typeof(decimal), "Allocation * Price");
With this approach, the TotalPrice will always be up to date if you change the Price or Allocation
If you don't have a seperate column, what happens when something makes the calculation execute again....
At some point the amount of code you have to add bend datatable to do what you want (without introducing a mass of potential 'erm features) will be more effort than just knocking up a class to hold the stuff.
Read from datatable write from databale isn't hard, nor is binding to a list of thingies.
Related
I have a datatable with almost 20 columns in it. in another DT i get only the columns I want. Recently my requirements have changed i.e. Firstly the number of columns in the original DT were constant but now it increases or decreases depending upon the data.
So now, if I statically provide the column names I need in my new DT it isnt of much use to me.
Is there any way in which I can include those columns which may or may not be in the Original Datatable????
For eg: col1|col2|col3|.......col20.
The columns that may bve present or absent fall between col12 and col 16. Is there anyway in which I could make it work????
EDIT:
I want col1,col2,col3 and all columns aftr col12...can I do it???
You can have total number of columns from datatable using
DataTable.Columns.Count
So you will know how many columns are there and you will know which column is in datatable and which is not.
I have a DataTable named 'dtStocksCriteria'; each cell in it should turn into a process function. So I should traverse all rows and columns.
For this purpose I have Parallel loop on rows. Then I select the Row with this Code:
DataView dv = new DataView(dtStocksCriteria);
dv.RowFilter = "xStockCode_FK = " + stock.Code;
After that in an Inner Parallel loop I should retrieve each column value with something like this code.
val = (double)dv[0]["column name"];
This Assignment take about 0.5 seconds which is too long for me. I want to reduce that to approximately 1 millisecond.
I have 398 rows and 110 columns in mt data table, in case that helps.
Does anyone have any ideas?
In C# working with DataView or DataRow or DataTable takes time.
BUT
If you use DataRow[int index] to retrive a cell value it should takes less time than using DataRow[string ColumnName] .
SO
When I use 'index' instead of 'ColumnName' it makes my code faster.
BUT
It is still slow because I have too much columns. So the best solution is to reduce the columns count first.
I'm using a SqlDataReader to add row by row into a datatable like follows:
while (reader.Read())
{
dataTable.LoadDataRow(reader.CurrentRow(), LoadOption.PreserveChanges);
}
This works, but I need to be able to avoid adding duplicate rows to the dataTable. I would love to be able to use the Contains or Find methods from the dataTable, but I can't find a way to turn the object[] from reader.CurrentRow() into a DataRow to compare to without adding it to a datatable.
I've looked into the option of making a hashset of the object[]s, and then adding them all at once to the datatable at the end, but I forgot that the default object IEqualityComparer only compares the reference.
Is there a feasible way of doing this without removing the duplicates at the end?
If removing the duplicates is the only way to go, what is the best way to do that?
EDIT:
I'm splitting distinct rows from the database into separate datatables in code. Each row from the query result is distinct, but sections of each row are not. Unfortunately I need to do exactly what my question is asking, as the results from the query are already distinct.
You didn't provide a ton of detail, but I hope this is comprehensive.
If you need a single column to be unique, then in your Columns collection in your datatable, specify the column like this:
DataTable appeals = new DataTable("Appeals");
appeals.Columns["PriorAppealNumber"].Unique = true;
DataColumn keyField = new DataColumn("AppealNumber", typeof(string));
appeals.Columns.Add(keyField);
If the uniqueness needs to span multiple rows, this is the method:
var myUniqueConstraint = new UniqueConstraint( new DataColumn[] {appeals.Columns[0], appeals.Columns[1], appeals.Columns[2]} );
appeals.Constraints.Add(myUniqueConstraint);
That will enforce the constraints BEFORE you try to commit back to the source database.
The easiest way is to actually make sure there are no duplicate rows at all - if you're querying relational database use DISTINCT - that will return only unique rows.
I have a DataSet with multiple DataTables that I'd like to bind to a chart with multiple column series. I expected each series to have different values respective to the DataTables in the DataSets; however, when the chart appears, both series display the same values in the Y column, the values from the first tables.
Here is a general idea what my code is like:
(I created and filled up a DataSet named diffCharts, diffCharts contains tables table1 and table2, both tables have columns Month and Amount)
Chart1.Series.Add("table1");
Chart1.Series["table1"].XValueMember = "Month";
Chart1.Series["table1"].YValueMembers = "Amount";
Chart1.Series.Add("table2");
Chart1.Series["table2"].XValueMember = "Month";
Chart1.Series["table2"].YValueMembers = "Amount";
Chart1.DataSource = diffCharts;
Chart1.DataBind();
Am I missing something? I've never bound a DataSet with multiple tables to a chart before.... Does MS know how to handle this?
I know this is an old post, but better late than never.
You can bind enumerable data sources directly to the DataPointCollection property in the series using the DataBind method. This way each series can be bound to a different table.
I am relatively new to C#, so there may be an adverse affect to this method that I am not aware of. It functions correctly in my limited testing.
MSDN link.
Chart1.Series.Add("table1");
Chart1.Series["table1"].Points.DataBind(table.AsEnumerable(), "nameofXaxis", "nameofYaxis, "nameofPropertyaxis");
Propertyaxis can be left as an empty string
I don't think you can do that.
You'll probably need to create a table with one column as the shared column for the X Axis (Month) and then two more columns for the Y values you want to graph.
The DataTable class has a Merge function that may do exactly what you need.
I have a problem with my asp.net program. I am doing a Datatable.Compute on a very large database with a like condition in it. The result takes something like 4 minutes to show or does a Request timeout. If I do the same request with a = and a fix text, it takes nearly 1 minute to show, which for my use is acceptable.
Here is the line that is so slow:
float test = (int)Datatbl.Tables["test"].Compute("COUNT(pn)", "pn like '9800%' and mois=" + i + " and annee=" + j);
I have been searching for a solution for 2 days.
Please help me.
Are you retrieving the data in your Datatable from a database? Do you have access to the database?
If so, one option is to research methods of moving this lookup and aggregation into the database instead of doing it in your C# code. Once it is in the database, if required, you could add indexes for the 'mois' and 'annee' columns which may speed up the look up considerably. If '9800' is a hardcoded value, then you could even add a denormalisation consisting of a boolean column indicating whether the 'pn' column begins with '9800' and put an index on this column. This may make the lookup very fast indeed.
There are lots of options available.
I found it.
I use the Dataview and send the result to a DataTable. This sped up the process 10 times
Here is an exemple:
DataView dv = new DataView(Datatbl.Tables["test"], filter, "pn", DataViewRowState.CurrentRows);
DataTable test = dv.ToTable();
and then you can use the "test" DataTable.