Is it possible to have a DataColumn in a DataTable that contains int and long values? It should return an int value if a valid int else it should return a long value.
For some background why I want to achieve this, I have released a product that creates the DataColumn of type int, but it should have been long from the start. Now I don't want to break existing projects that explicitly casts the value to int, but I would like to allow long values in the column.
Is there an event I can subscribe to on the DataTable to convert the value to int?
The following code should execute correctly.
DataTable dataTable = new DataTable();
dataTable.Columns.Add("IntAndLong", typeof(long));
DataRow intRow = dataTable.NewRow();
intRow[0] = 123;
dataTable.Rows.Add(intRow);
DataRow longRow = dataTable.NewRow();
longRow[0] = 3000000000;
dataTable.Rows.Add(longRow);
long longValue = (long)dataTable.Rows[1][0];
int intValue = (int)dataTable.Rows[0][0];
I would suggest collecting the datacolumn value in a long type variable, check its value to be less than int.MaxValue and bigger than int.MinValue and then cast it to an int variable if you need it there.
Related
I am brand new at using Datatables.
I am trying to take two data tables and combine them and if the two tables have columns with matching headers then add the data in those columns together into a new column.
Another issue is that the headers are being created dynamically so I never know what the name of the header will be.
DataTable 1:
TeamName
Date1
Date2
First
int value
int value
Second
int value
int value
DataTable 2:
TeamName
Date2
Date3
First
int value
int value
Second
int value
int value
New Table:
TeamName
Date1
Date2
Date3
First
int value
int value1 + int value2
int value
Second
int value
int value1 + int value2
int value
If anyone has any insight on how to even get start with doing this with C# and/or LINQ I would really appreciate it.
I have some code but it just combines the tables by including everything, it basically looks like the two tables just side by side, nothing is mixed together.
DataTable targetTable = dt1.Clone();
var dt2Columns = dt2.Columns.OfType<DataColumn>().Select(dc =>
new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping));
var dt2FinalColumns = from dc in dt2Columns.AsEnumerable()
where targetTable.Columns.Contains(dc.ColumnName) == false
select dc;
targetTable.Columns.AddRange(dt2FinalColumns.ToArray());
var rowData = from row1 in dt1.AsEnumerable()
join row2 in dt2.AsEnumerable()
on row1.Field<string>("ScrumTeam") equals row2.Field<string>("ScrumTeam")
select row1.ItemArray.Concat(row2.ItemArray.Where(r2 => row1.ItemArray.Contains(r2) == false)).ToArray();
foreach (object[] values in rowData)
targetTable.Rows.Add(values);
Not sure LINQ is making your life any easier here
//ensure the dt2 column exists in dt1
foreach(DataColumn dc2 in dt2.Columns)
if(!dt1.Columns.Contains(dc2.ColumnName))
dt1.Columns.Add(dc2.Name, dc2.DataType);
//index the rows
var d = dt1.Rows.Cast<DataRow>().ToDictionary(r => r["TeamName"]);
//merge the tables, dt2 into dt1
foreach(DataRow r2 in dt2){
DataRow r1;
//handle dt2 team name absence from dt1
if(!d.ContainsKey(r2["TeamName"])){
d[r2["TeamName"]] = r1 = dt.NewRow();
dt1.AddRow(r1);
}
//index now surely contains r1; get it
r1 = d[r2["TeamName"]];
//merge data from 2 into 1
foreach(DataColumn dc2 in dt2.Columns){
//skip the PK
if(dc2.ColumnName == "TeamName")
continue;
//all the values seem to be int. if not true add some "if type is..." handling here
r1[dc2.ColumnName] = (int)r1[dc2.ColumnName] + (int)r2[dc2.ColumnName];
}
}
Your code says "ScrumTeam" but question tables says "TeamName" - you may have to adjust the code above to cater for your scenario(treat as pseudocode)
I've a datatable, with column A, B, C. I've set column A's "is identity" property to true, but I can't add any row to the table now.
The code I'm trying is this:
dsA.dtA row = dsA.dtA.NewdtARow();
row.B = 1;
row.C = 2;
dsA.dtA.Rows.Add(row);
I'm getting NoNullAllowedException, but I don't understand why. Column A is PK as well. If I tried to set row.A = 5 (or any similiar) I'll get an error when I try to update the datatable saying "cannot insert explicit value for identity column in table when identity_insert is set to off"
How can I solve this issue? It's frustrating.
Do this way. Reference link
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 1;
column.AutoIncrementStep = 1;
// Add the column to a new DataTable.
DataTable table = new DataTable("table");
table.Columns.Add(column);
DataRow oRow = table.NewRow();
table.Rows.Add(oRow);
Open the designer of the dataset xsd file and set the AutoIncrement, AutoIncrementSeed and AutoIncrementStep property of the column A in datatable for an existing column.
Try one of the these two:
Set field values:
row.A = null;
row.B = 1;
row.C = 3;
Add row to DataTable:
dtA.Rows.Add(null,1,2);
They are both the same just try any of them and it should get you going. Also remember that whenever you want to make a column auto-increment in DataTable then you have to insert null into it.
The way that I do it is
public void AppendtodtA(int num1, doubledouble1, string string1)
{
object[] RowArray = new object[] {null,(int)num1, (double) doubledouble1, (string) string1}
DataRow CurrentRow = dtA.NewRow();
CurrentRow.ItemArray = RowArray;
dtA.Rows.Add(CurrentRow);
}
use ItemArray property and leave a null in the place of the autoincremented column
AppendtodtA(MyNumber,MyDouble,MyString);
Then just call the method with your variables.
The above error message appears when I am trying to get Column Value from Datatable.
This is what I find in the stacktrace:
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1
source)
and this in the TargetSite when debugging:
{ Boolean b__0(System.Data.DataRow)}
Here is my code:
DataTable hr = new DataTable();
hr.Columns.Add("BookingDate");
hr.Columns.Add("BookingId");
hr.Columns.Add("BookingSource");
hr.Columns.Add("CheckInDate");
hr.Columns.Add("CheckOutDate");
for (int i = 0; i < gmisc.GetModifiedBookings(gmoreq).Bookings.Length; i++)
{
hr.Rows.Add();
hr.Rows[i]["BookingDate"] = Convert.ToDateTime(gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingDate.ToString());
hr.Rows[i]["BookingId"] = Convert.ToInt64(gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingId.ToString());
hr.Rows[i]["BookingSource"] = gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingSource.ToString();
hr.Rows[i]["CheckInDate"] = Convert.ToDateTime(gmisc.GetModifiedBookings(gmoreq).Bookings[i].CheckInDate.ToString());
hr.Rows[i]["CheckOutDate"] = Convert.ToDateTime(gmisc.GetModifiedBookings(gmoreq).Bookings[i].CheckOutDate.ToString());
}
Int64 BookingId = (from DataRow dr in hr.Rows
where (Int64)dr["BookingId"] == BookId
select (Int64)dr["BookingId"]).FirstOrDefault();
TextBox1.Text = Convert.ToString(BookingId);
Where did I go wrong, if somebody can please tell me.
Check your code, the very first two lines:
hr.Rows[i]["BookingDate"] = Convert.ToDateTime(gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingDate.ToString());
hr.Rows[i]["BookingId"] = Convert.ToInt64(gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingId.ToString());
if gmisc.GetModifiedBookings(gmoreq).Bookings[i].BookingDate is null then ???
you are trying to convert it into string and then to datetime
if null then .ToString will give error "Specified cost......."
and same will happen at the time of converting to datetime.
If dr["BookingId"] is never null (otherwise add null check)
Use
Int64 BookingId = (from DataRow dr in hr.Rows
where Int64.Parse(dr["BookingId"].ToString()) ==BookId
select Int64.Parse(dr["BookingId"].ToString())).FirstOrDefault();
Instead of
Int64 BookingId = (from DataRow dr in hr.Rows
where (Int64)dr["BookingId"] == BookId
select (Int64)dr["BookingId"]).FirstOrDefault();
When you create a data column using the Add(string) overload, the type of the column is string (see http://msdn.microsoft.com/en-us/library/52xzw8tf.aspx). You cannot cast a string directly to Int64 or DateTime.
Use the Add(string, Type) overload or the Add(string, Type, string) overload to specify the type of the column's data.
I have a datarow, but how can i convert it to an int ?
I tried this, but it doesn't work.
dsMovie = (DataSet)wsMovie.getKlantId();
tabel = dsMovie.Tables["tbl_klanten"];
eersteRij = tabel.Rows[0];
(Int32.Parse(eersteRij.ToString())
A DataRow is an object; it is not an integer. A DataRow contains one or more columns of data. You can index into the DataRow to access the values of these coulmns.
If table tbl_klanten contains one column, and that column is an integer, you can do the following:
var myInt = (int)eersteRij[0];
if the column is a string containing the value of an integer,
var myInt = int.Parse(eersteRij[0]);
If the column is named klant_id...
var myInt = (int)eersteRij["klant_id"];
if the column is a string containing the value of an integer,
var myInt = int.Parse(eersteRij["klant_id"]);
Simply use the Field method:
int result = row.Field<int>("ColName");
The Field method also supports nullable types:
The Field method provides support for accessing columns as nullable
types. If the underlying value in the DataSet is Value, the returned
nullable type will have a value of null.
And please notice:
The Field method does not perform type conversions. If type conversion is required, you should first obtain the column value by using the Field method. The column value should then be converted to another type.
Because even at that level of hierarchy you still have a DataRow and you can't convert a DataRow to int.. a value could be converted though.
And why are you converting whole DataRow to int.. usually you would like to get a value in a cell at a row so try, Somthing like this:
int value = (int)eersteRij.Items[0];
where 0 can be replaced by the cell position(int) or Column name(string)
You'll need to know which index the object you want is on, and cast that to an int, e.g.:
int value = (int)eersteRij[0];
DataSet dataSet = getDataFromDatabase();
DataRow tableRow = dataSet.Tables[0].Rows[0];
int valueAsInteger = Convert.ToInt32(tableRow["COLUMN_NAME"]);
I tend to use IndexOf() when looping thru the dataTable.
foreach (DataRow row in DataTable.table.Rows)
{
int index = dataTable.Rows.IndexOf(row);
}
I am trying to figure out how to append a column to Linq query results based on the max value of the query. Essentially, I want to create an EnumerableRowCollection of DataRows that would include a max value record with the same value for each record. So if i have a hundred records returned through the query, I want to next calculate the max value of one of the fields, then append that max value to the original query table:
DataTable dt = new DataTable();
dt = myDataSet.myDataTable;
EnumerableRowCollection<DataRow> qrySelectRecords =
(from d in dt.AsEnumerable()
where d.Field<DateTime>("readingDate") >= startDate && g.Field<DateTime>("readingDate") <= endDate
select d);
Here's where I need help:
double maxValue = qrySelectRecords.Field<double>("field1").Max();
foreach (DataRow dr in qrySelectRecords)
{
qrySelectRecords.Column.Append(maxValue)
}
Couple points, first: new DataTable() is redundant; you're instantiating a rather expensive object that will never be used because you're overwriting the reference in the very next line. You should consider removing the initialization and then joining the declaration and the actual assignment on one line.
Getting to the real question. DataRows cannot have columns added to them directly; you have to add the column to the entire DataTable containing those rows. Once that's done, just set the value. As long as you don't need the operation translated into an external query language like SQL, you can inline this operation using a monadic extension method:
DataTable dt = myDataSet.myDataTable;
dt.Columns.Add("MaxField1");
EnumerableRowCollection<DataRow> qrySelectRecords =
(from d in dt.Rows().AsEnumerable().OfType<DataRow>()
where d.Field<DateTime>("readingDate") >= startDate
&& d.Field<DateTime>("readingDate") <= endDate
let m = dt.AsEnumerable().Max(dr=>dr.Field<double>("field1"))
select d.WithColumnSet("MaxField1", m));
...
public static DataRow WithColumnSet(this DataRow input, string columnName, object value)
{
input[columnName] = value;
return input;
}