Creating a dynamic variable - c#

Ive been working on a program that allows me to updload data from my sql server DB into a SOAP service. I can successfully upload the data into the service. The problem is that the same row is being inserted. The following is a part of my code: `
List<service1.SDataRow> ArrayOfSData = new List<ne_service_demo2.service1.SDataRow>();
//data to be uploaded.
service1.SDataRow row1 = new service1.SDataRow();
foreach (DataRow dRow in dTable.Rows)
{
row1.SensorTimeStamp = dRow["SensorTimeStamp"].ToString();
row1.SensorID = dRow["SensorID"].ToString();
row1.PercentFull = dRow["PercentFull"].ToString();
row1.Temp = dRow["Temp"].ToString();
row1.TempReading = dRow["TempReading"].ToString();
row1.Sig = dRow["Sig"].ToString();
row1.SignalReading = dRow["SignalReading"].ToString();
row1.Noi = dRow["Noi"].ToString();
row1.NoiseReading = dRow["NoiseReading"].ToString();
row1.Cou = dRow["Cou"].ToString();
row1.CountReading = dRow["CountReading"].ToString();
row1.NewPercentFull = dRow["NewPercentFull"].ToString();
row1.Current_Gallons_In_Tank = dRow["Current_Gallons_In_Tank"].ToString();
ArrayOfSData.Add(row1);
}
service1.SensorData sd = new service1.SensorData();
sd.API_ACCESS_KEY = "7e070c1981ccc368483a207801be17aa17b2334c";
sd.AccountCode = "0000000";
sd.SData = ArrayOfSData.ToArray();
// Asynchronous call
ws.PostSensorDataCompleted += WebSeviceResult;
ws.PostSensorDataAsync(sd);`
As I loop through my DB table, all data goes to the appropriate fields or columns. Again, the problem is that I get the same row x amount of times. I know the problem is "row1" because it is constantly being updated with new values while still keeping the list count. However, I can not make row1 a list type because it must be of SDataRow type since that is the class that links my service to the columns of my DB. I also tried using the List.Clear() method to clear out my list within my loop but did not work. When I tried clearing the list after every iteration I would get an error saying "Item has already been added." So in theory the clear() method should work, its the row1 that is causing problems. Does anyone know of a work around or a way to make

You are creating an instance of the SDataRow outside the loop. Inside the loop, you are setting the properties of that same instance (overwriting them each iteration), then adding that same instance to the list.
Change that part of the code to this:
foreach (DataRow dRow in dTable.Rows)
{
service1.SDataRow row1 = new service1.SDataRow();
So you need to create new instances inside the foreach loop

Related

When I am going through a foreach loop, it changing everything in my list to the new data getting added?

I have a method I am using for a test that takes the data in a table row, turns it into a string then uses the Split() function to add each different string to an object in my class. I then take that and try and add it to a list of the same class. Each time it runs through the foreach loop it is just updating each object to the new data that is supposed to be added so that the data is the same in each index whereas it is supposed to be different. How can I fix this?
Here is the method:
public List<IMUItemModel> tableData()
{
_webDriver.Wait.UntilPageLoadIsComplete(60);
List<IMUItemModel> IMUDataList = new List<IMUItemModel>();
IMUItemModel IMUData = new IMUItemModel();
foreach (var row in IMUDataTableRows)
{
string column = row.Text;
var split = column.Split(' ');
IMUData.MedVendID = split[0];
IMUData.DeviceSerialNumber = split[1];
IMUData.ItemID = split[2];
IMUData.Station = split[3];
IMUData.Console = split[4];
IMUDataList.Add(IMUData);
Console.WriteLine(IMUData.MedVendID);
}
return IMUDataList;
}
You are creating a single instance of IMUData for entire list and so, the same reference is being assigned the values in each iteration. At the end of the iteration, all the items will have the data of last item because you just kept on updating the same reference.
To fix this,
move the below line inside the foreach loop
IMUItemModel IMUData = new IMUItemModel();
This will ensure you have a new reference each time you add an item to the list.

Adding DataRow items from collection of values

I am trying to create a DataRow which gets some values from hard-coded strings or string variables, and the rest of the values from a collection's values, System.Collections.Generic.Dictionary<string, double>.ValueCollection to be specific. In my attempt below, I'm casting to an array but that doesn't work.
DataTable source = new DataTable();
foreach (string sample in GridSource.SampleName)
{
SampleDictionaries sd = GridSource.Data.Where(x => GridSource.Data.IndexOf(x) == GridSource.SampleName.IndexOf(sample)).First();
source.Rows.Add(sample, "Average", sd.Avg.Values.ToArray());
source.Rows.Add("", "Std. Deviation", sd.StdDev.Values.ToArray());
}
The code above produces this:
I understand what is happening here. My question is this: is there an easy way to tell the DataRow "Fill the remaining column values with this collection," or am I going to have to come up with some loop to do it?
what you can do is create the row from the datatable.NewRow() method. Then you can have the items array of the row equal an array of data:
DataTable source = new DataTable();
foreach (string sample in GridSource.SampleName)
{
DataRow temp = source.NewRow();
SampleDictionaries sd = GridSource.Data.Where(x => GridSource.Data.IndexOf(x) == GridSource.SampleName.IndexOf(sample)).First();
temp.ItemArray = new object[]{sample, "Average"}.Concat(sd.Avg.Values.ToArray());
source.Rows.Add(temp);
temp = source.NewRow();
temp.ItemArray = new object[]{"", "Std. Deviation".Concat(sd.StdDev.Values.ToArray());
}
Found an answer, with help from KMoussa!
source.Rows.Add(new object[] { "", "Std. Deviation"}.Concat(sd.StdDev.Values.Cast<object>().ToArray()).ToArray());
Very similar to what he recommended, but it was missing a second cast to array at the end.

Fill DataTable using array of NewRows

and thanks for the help! I'm trying to fill a DataTable before its pulled in a Report from Microsoft Reporting Services.
I originally thought I could run a for look (depending on how many rows there are in my "MainTable", and assign each category and flush it into a Rows.Add and repeat but apparently I cannot Row.Add the same name NewRow. Here's what I have thus far. thanks for the help!:
MyDataSet.ESSRow newESS = MyDataSet.ESS.NewESSRow();
for (int i = 0; i < ds.Tables["MainTable"].Rows.Count; i++)
{
DataRow dRow = ds.Tables["MainTable"].Rows[i];
if(Convert.ToInt32(dRow.ItemArray.GetValue(9).ToString()) > ShiftDelta)//checks if instance is longer than a shift
{
newESS.Station = "7";
newESS.Switch ="7";
newESS.Start = dRow.ItemArray.GetValue(6).ToString();
newESS.Stop = dRow.ItemArray.GetValue(7).ToString();
newESS.SwitchIs = dRow.ItemArray.GetValue(8).ToString();
TimeSpan t = TimeSpan.FromSeconds(Convert.ToInt32(dRow.ItemArray.GetValue(9).ToString()));
newESS.Duration = string.Format("{0:D2}h:{1:D2}m:{2:D2}s", t.Hours, t.Minutes, t.Seconds);
MyDataSet.ESS.Rows.Add(newESS); }
}
Also try to rather use importRow as this does not give the annoying row already belongs to another table error.
Don't try to add the same row several times, instead create a new row to add in each iteration of the loop. This can be done most simply by just moving the declaration of newESS to be inside of the loop rather than outside of the loop. Beyond that, you should also move it to be inside of the if statement so that you aren't creating a new row if you aren't going to add one.

How do I load a list via a data set from SQL Server into ListView?

I have what seems to be a simple question but its killing me trying to find out.
I have a form in which I have a ListView. In this ListView I would like to populate it with data from a SQL Server 2008 database table.
public void LoadList()
{
DataTable dtable = budget_MainDataSetReceipt.Tables["Receipt"];
listView1.Items.Clear();
for (int i = 0; i < dtable.Rows.Count; i++)
{
DataRow drow = dtable.Rows[i];
if (drow.RowState != DataRowState.Deleted)
{
ListViewItem lvi = new ListViewItem(drow["ReceiptID"].ToString());
lvi.SubItems.Add(drow["DateCleared"].ToString());
lvi.SubItems.Add(drow["CategoryID"].ToString());
lvi.SubItems.Add(drow["Amount"].ToString());
lvi.SubItems.Add(drow["Store"].ToString());
lvi.SubItems.Add(drow["DateEntered"].ToString());
listView1.Items.Add(lvi);
}
}
}
I keep getting an
Object reference not set to an instance of an object
error, and I can't figure out why. There are about 5 rows of data in my database, so in my mind, there should be 5 rows of data within the list view.
Can anyone tell me what I am missing? I can post more code if that would be helpful.
I have tried calling the LoadList() method in several ways:
Before the method itself
With the InitializeComponent() method
I have tried the following syntax
this.LoadList();
this.Form1.LoadList();`
I have also tried to initialize the DataTables type with the following:
DataTables dt = new DataTables //did not work
My hunch would be: you're assuming for all columns in your DataRow that they're present and not null - that's a bit of a dangerous assumption.
I would change your assignments to use a method that checks for DBNull before returning the string:
public string SafeGetString(DataRow row, string columnName)
{
if(row[columnName] != null && row[columnName] != DBNull.Value)
{
return row[ColumName].ToString();
}
return string.Empty;
}
so your could would look like:
ListViewItem lvi = new ListViewItem(SafeGetString(drow, "ReceiptID"));
lvi.SubItems.Add(SafeGetString(drow, "DateCleared"));
// and so forth
This way, if any of the columns should contain a NULL, you would get back an empty string - instead of running into a NULL.ToString() that causes the error you're seeing.

Adding a Row to a DataTable question

Greetings everyone-
In my code below I'm trying to add a Row from an existing DataTable (dtResult) into a new DataTable (dtCopyResult) if email address does not match. So I guess my knowledge of ADO.NET is not up to par because whenever I try to run my below code, I get an "This Row already belongs to another table". Please let me know how I can fix this..
Many Thanks
if (checkBox1.Checked)
{
for (int i = dtResult.Rows.Count - 1; i >= 0; i--) //dtResult is a DataTable
{
foreach (object email in emails) //emails is an ArrayList of email addresses
{
if (email.ToString().ToUpper() != dtResult.Rows[i][3].ToString().ToUpper())
{
dtCopyResult.Rows.Add(dtResult.Rows[i]); //dtCopyResult is a new blank DataTable that I'm trying to add rows to
}
}
}
}
As the error message tells you, a DataRow belongs to a particular DataTable; you cannot just take it and add it to another one. What you can do is either
create a new DataRow and fill it with the values from the old DataRow or
use the DataTable.ImportRow method:
dtCopyResult.ImportRow(dtResult.Rows[i]);
You can use ImportRow function, full example here http://support.microsoft.com/kb/308909
One thing I noticed is that the new row will get added multiple times; once for each item in the emails collection.
You either need to keep a local list of items already added or loop through dtCopyResult to make sure you have not already added the email.
List<string> alreadyAdded = new List<string>();
if (email.ToString().ToUpper() != dtResult.Rows[i][0].ToString().ToUpper()
&& !alreadyAdded.Contains(email.ToString()))
{
dtCopyResult.ImportRow(_dt1.Rows[i]);
alreadyAdded.Add(email.ToString());
}
it means the adding row is belong to "dtResult" and DataRow is an "Object" that represent data. Not data itselfs. so in this case u try to add DataRow object that belong to another table which will error.
another way to do is copy everything to dtCopy and delete it if condition mismatch.
Array is mainly to used to stored various type of object. In this case, if u gonna store only email u should use
List<string> emails = new List<string>();
emails.Add("test#example.com");
to enumerate rows for deleteing data
List<DataRow> removing = new List<DataRow>();
foreach(var row in table.AsEnumerable()) // or table.Rows
if(...condition)removing.Add(row);
foreach(var row in removing)table.Rows.Remove(row);
the reason to use 'removing' is if u loop through rows and removing it at the same time, means u change the enumerate which will cause error. becus .Net is not happy when u pull out something its looping.
Try replacing
dtCopyResult.Rows.Add(dtResult.Rows[i]);
with
DataRow rowToBeCopied = dtCopyResult.NewRow();
//Copy the row values..
rowToBeCopied.X = dtResult.Rows[i].X;
//Copy the remaining row values
dtCopyResult.Rows.Add(rowToBeCopied);

Categories