Current Code:
foreach (Expressions e in expressionObj)
{
if ((e.Expression != null) && (e.ColumnName != null))
{
newtable1.Columns.Add(new DataColumn(e.ColumnName, typeof(decimal), e.Expression));
}
}
I have an expression as ID+ID which is to be added as new column in the datatable as SUM-ID where ID=2, but the result got is 22 instead of 4.
Let's see:
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ID", typeof(decimal)));
dt.Columns.Add(new DataColumn("SUM-ID", typeof(decimal), "ID + ID"));
var row = dt.NewRow();
row["ID"] = 2;
dt.Rows.Add(row);
var val = dt.Rows[0]["SUM-ID"];
Result: val is 4 as expected.
Let's try something else:
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ID", typeof(string)));
dt.Columns.Add(new DataColumn("SUM-ID", typeof(decimal), "ID + ID"));
var row = dt.NewRow();
row["ID"] = "2";
dt.Rows.Add(row);
var val = dt.Rows[0]["SUM-ID"];
Result: val is 22
Conclusion: Your ID column is of type string but it needs to be a numeric type instead otherwise string concatenation is used.
Update: If you cannot (or don't want to) set the datatype of the column then you can use Convert inside the expression: 2 * Convert(ID, 'System.Int32')
Related
I have a dataset where I am pulling value from the database, now after that, I want to add some more rows to it. I get four columns from the database: approverName, approverEmail, approverRole, approvalStatus
DataSet dsResult = new DataSet();
dsResult = getDataFromDatabase();
DataTable dt = new DataTable("MyTable");
dt.Columns.Add(new DataColumn("approverName", typeof(string)));
dt.Columns.Add(new DataColumn("approverEmail", typeof(string)));
dt.Columns.Add(new DataColumn("approverRole", typeof(string)));
dt.Columns.Add(new DataColumn("approvalStatus", typeof(string)));
DataRow dr = dt.NewRow();
dr["approverName"] = "John";
dr["approverEmail"] = "John#gc.com";
dr["approverRole"] = "Manager";
dr["approvalStatus"] = "Pending";
dt.Rows.Add(dr);
dsResult.Tables.Add(dt);
But after executing code I don't see this manually added value in the dataset. It only shows the value which I had after executing line 2 of code
You don't need to create another DataTable.
Append new row to existing DataTable
DataSet dsResult = new DataSet();
dsResult = getDataFromDatabase();
DataTable dt = dsResult.Tables[0]; //Get Reference to existing table
DataRow dr = dt.NewRow();
dr["approverName"] = "John";
dr["approverEmail"] = "John#gc.com";
dr["approverRole"] = "Manager";
dr["approvalStatus"] = "Pending";
dt.Rows.Add(dr);
Is there any way to do an increment number from 1,2,3 and so on for my column in my datatable?
For example similar to column "Code" below
or at least is there any other way that i can name the numbers manually?
Here's what I've tried (but not working)
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 1;
column.AutoIncrementStep = 1;
Thanks for your reply
AutoIncrement is indeed the right approach here. You might be missing something else, but the following code does work:
var dt = new DataTable();
dt.Columns.Add(new DataColumn { ColumnName = "Code", AutoIncrement = true, DataType = typeof(int) });
dt.Columns.Add(new DataColumn { ColumnName = "Resource Type", DataType = typeof(string) });
dt.Columns.Add(new DataColumn { ColumnName = "Number of hits", DataType = typeof(int) });
var newRow = dt.NewRow();
newRow[1] = "Testing";
newRow[2] = 3;
dt.Rows.Add(newRow);
var newRow2 = dt.NewRow();
newRow2[1] = "Testing 2";
newRow2[2] = 6;
dt.Rows.Add(newRow2);
And when inspecting dt, the result is:
Code Resource Type Number of hits
0 Testing 3
1 Testing 2 6
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Date", typeof(String)));
dt.Columns.Add(new DataColumn("Time", typeof(String)));
dt.Columns.Add(new DataColumn("Function", typeof(String)));
dt.Columns.Add(new DataColumn("Log Level", typeof(String)));
dt.Columns.Add(new DataColumn("Message", typeof(String)));
When i query DataTable then get DataRows[]
DataRow[] result = dt.Select("Function ='" + strfunction + "'");
Now i want to add that result in DataTable
dt.Rows.Add(result);
But i am getting error
Input array is longer than the number of columns in this table.
try this
foreach (DataRow row in result)
dt.Rows.Add(row);
DataRowCollection.Add() has two overloads:
Add(DatarRow row);
Add(params object[] values);
The one you are currently using is Add(params object[] values); since you are passing an array of a class with base class of object. So you are searching in the same table, getting the same number of columns indeed, but the problem is that; you expect each element of the array to be inserted as a DataRow, but there is only one row inserted and each element of the array DataRow[] result is assigned for columns
With:
dt.Rows.Add(new object[] { "Date", "Time", "a", "Log Level", "Message" });
DataRow[] result = dt.Select("Function ='a'");
foreach (DataRow r in dt.Rows)
{
/* Log r or inpect */
}
No exception was thrown in my test because the result array had only 1 element (as search result).
If i have more then 5 elements in result; since i can't insert 6 column values in a 5 column table it will throw exception.
And the correct way to do it is interating search results array and adding a new row for each array element; using DataRow.ItemArray property
You can try the following which worked for me:
DataRow[] result = dt.Select("Function ='" + strfunction + "'");
foreach (DataRow r in result)
{
dt.Rows.Add(r.ItemArray);
}
Instead of directly adding the DataRow to the DataTable, how about creating a foreach loop and creating a separate DataRow from the DataTable, filling the data and adding it into the DataTable. For example:
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Date", typeof(String)));
dt.Columns.Add(new DataColumn("Time", typeof(String)));
dt.Columns.Add(new DataColumn("Function", typeof(String)));
dt.Columns.Add(new DataColumn("Log Level", typeof(String)));
dt.Columns.Add(new DataColumn("Message", typeof(String)));
//Dummy data added
DataRow dr = dt.NewRow();
dr[0] = "aa";
dr[1] = "bb";
dr[2] = "cc";
dr[3] = "dd";
dr[4] = "ee";
dt.Rows.Add(dr);
string strfunction = "cc";
DataRow[] result = dt.Select("Function ='" + strfunction + "'");
//Initialize Datarow here. I am using the one which is defined above
dr = null;
foreach (var item in result)
{
dr = dt.NewRow();
dr[0] = item[0];
dr[1] = item[1];
dr[2] = item[2];
dr[3] = item[3];
dr[4] = item[4];
dt.Rows.Add(dr);
}
Hope this helps.
public void BindGrid(int rowcount)
{
btnsubmit.Visible = true;
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(new System.Data.DataColumn("Employee ID", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("Leave Type", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("From", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("To", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("No:of Days", typeof(String)));
if (ViewState["CurrentData"] != null)
{
for (int i = 0; i < rowcount + 1; i++)
{
dt = (DataTable)ViewState["CurrentData"];
if (dt.Rows.Count > 0)
{
dr = dt.NewRow();
dr[0] = dt.Rows[0][0].ToString();
}
}
dr = dt.NewRow();
dr[0] = lblempID.Text;
dr[1] = ddlleavetype.SelectedItem.Text.ToString();
dr[2] = txtfrom.Text.ToString();
dr[3] = txtto.Text.ToString();
dt.Rows.Add(dr);
}
else
{
dr = dt.NewRow();
dr[0] = lblempID.Text;
dr[1] = ddlleavetype.SelectedItem.Text.ToString();
dr[2] = txtfrom.Text.ToString();
dr[3] = txtto.Text.ToString();
dt.Rows.Add(dr);
}
// If ViewState has a data then use the value as the DataSource
if (ViewState["CurrentData"] != null)
{
gvLeave.DataSource = (DataTable)ViewState["CurrentData"];
gvLeave.DataBind();
}
else
{
// Bind GridView with the initial data assocaited in the DataTable
gvLeave.DataSource = dt;
gvLeave.DataBind();
}
// Store the DataTable in ViewState to retain the values
ViewState["CurrentData"] = dt;
}
In my page having from date textbox and todate textbox..i want to calculate the between two dates ,please help me
I'm not very familiar with the DataTable object, so take this answer as an idea. :-)
Why don't you specify the Rows with the actual type?
dt.Columns.Add(new System.Data.DataColumn("From", typeof(DateTime)));
dt.Columns.Add(new System.Data.DataColumn("To", typeof(DateTime)));
dt.Columns.Add(new System.Data.DataColumn("No:of Days", typeof(int)));
And after this you can Parse the data of txtfrom like dr[2] = DateTime.Parse(txtfrom.Text.ToString()) and assign it to your DataRow. Same goes for txtto.
After this, you are able to calculate the days between by using:
dr[4] = (int)((dr[2] -dr[3]).TotalDays);
If this doesn't work, try to save the parsed Dates in objects like so:
DateTime from = DateTime.Parse(txtfrom.Text.ToString());
DateTime to = ...;
TimeSpan t1 = to - from;
dt[4] = (int)(t1.TotalDays);
If they are in a textbox you will need to parse them first using DateTime.Parse. This is under the assumption that the strings are in the correct format
DateTime myDate = DateTime.Parse(myDateString);
To calculate the days between two dates you can try this
TimeSpan span =date1-date2;
var days = span.TotalDays;
Try this Code :
Var Day= DateTime.Parse(todate.Text).Subtract(DateTime.Parse(fromdate.Text)).Days;
I have created a datatable and trying to insert that datatable through SqlBulkCopy but somehow it doesn't seem to work for me....
I got the error,
The given value of type DateTime from the data source cannot be converted
to type decimal of the specified target column.
My Datasource is,
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("EmpId", typeof(Int64)));
dt.Columns.Add(new DataColumn("FromDate", typeof(DateTime)));
dt.Columns.Add(new DataColumn("ToDate", typeof(DateTime)));
dt.Columns.Add(new DataColumn("DaysPresent", typeof(decimal)));
dt.Columns.Add(new DataColumn("OpeningAdvance", typeof(double)));
dt.Columns.Add(new DataColumn("AdvanceDeducted", typeof(double)));
dt.Columns.Add(new DataColumn("RemainingAdvance", typeof(double)));
dt.Columns.Add(new DataColumn("SalaryGiven", typeof(double)));
dt.Columns.Add(new DataColumn("CreatedDate", typeof(DateTime)));
foreach (GridViewRow row in gridEmployee.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
DataRow dr = dt.NewRow();
dr["EmpId"] = Convert.ToInt64(((HiddenField)row.Cells[0].FindControl("HiddenId")).Value);
dr["FromDate"] = Convert.ToDateTime(GetMonthNumberFromAbbreviation(fromdate[1].ToString()) + '/' + fromdate[0].ToString() + '/' + fromdate[2].ToString());
dr["ToDate"] = Convert.ToDateTime(GetMonthNumberFromAbbreviation(todate[1].ToString()) + '/' + todate[0].ToString() + '/' + todate[2].ToString());
dr["DaysPresent"] = Convert.ToDecimal(((TextBox)row.Cells[3].FindControl("TxtDaysPresent")).Text);
dr["OpeningAdvance"] = Convert.ToDouble(((TextBox)row.Cells[4].FindControl("txtOpeningAdv")).Text);
dr["AdvanceDeducted"] = Convert.ToDouble(((TextBox)row.Cells[5].FindControl("TxtAdvanceDeducted")).Text);
dr["RemainingAdvance"] = Convert.ToDouble(((TextBox)row.Cells[6].FindControl("TxtClosingAdvance")).Text);
dr["SalaryGiven"] = Convert.ToDouble(((TextBox)row.Cells[7].FindControl("TxtSalary")).Text);
dr["CreatedDate"] = Convert.ToDateTime(System.DateTime.Now.ToString());
dt.Rows.Add(dr);
}
}
SqlBulkCopy sbc = new SqlBulkCopy(connectionString);
sbc.DestinationTableName = "SalaryDetails";
sbc.WriteToServer(dt);
sbc.Close();
And my destination Table looks like this,
alt text http://img231.imageshack.us/img231/5448/mytable.jpg
You need to specify a column mapping, as you don't have the same number of columns in the DataTable and the destination table.
You can do it like this:
sbc.ColumnMappings.Add("EmpId", "EmpId");
sbc.ColumnMappings.Add("FromDate", "FromDate");
// and so on, with the rest of the columns; and after that comes
sbc.WriteToServer(dt);
sbc.Close();